当前位置: 首页 > 知识库问答 >
问题:

如何显示加载百分比以及如何在没有JavaScript的情况下做到这一点?

欧阳杰
2023-03-14
<?php 
$x=1;
while($x<=100) {
   echo "Loading: $x %<br>";
   $x++;
}   
?>

更新:我知道我应该使用JS和/或Ajax来实现它,我只是想知道是否有一种方法也可以在PHP中实现它:)

共有1个答案

贺聪
2023-03-14

跟踪长时间运行的任务很常见,但第一次实现并不容易。这里有一个完整的例子。

假设您当前有以下任务,并希望向访问者显示进度条。

phptask.php

  <?php

  $total_stuffs = 200;
  $current_stuff = 0;
  while ($current_stuff < $total_stuffs) {
    $progress = round($current_stuff * 100 / $total_stuffs, 2);

    // ... some stuff
    sleep(1);

    $current_stuff++;
  }
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <title>My Task!</title>
    </head>
    <body>

        <a id="run_task" href="#">Run task</a>

        <div id="task_progress">Progression: <span id="task_progress_pct">XX</span>%

        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

        <script type="text/javascript">

            $('#run_task').click(function(e) {
                e.preventDefault();
                $.get('task-launch.php');
            });

        </script>

    </body>
</html>
<?php

  // launches the task in background
  // see https://stackoverflow.com/a/12341511/731138 for details about the arguments
  exec("/usr/bin/php task.php > /dev/null 2>&1 &");

这里有3个问题:

>

  • 点击多次运行按钮可以多次运行任务,如何避免同时在后台运行多个任务?

    任务是在服务器端运行的,所以我们需要做一些事情来访问服务器并请求进度信息。

    <?php
    
    require("Sync.php");
    
    $total_stuffs = 200;
    $current_stuff = 0;
    
    $shared = new Sync("some_file.txt");
    $shared->progress = 0;
    
    while ($current_stuff < $total_stuffs) {
      $shared->progress = round($current_stuff * 100 / $total_stuffs, 2);
    
      // ... some stuff
      sleep(1);
    
      $current_stuff++;
    }
    
    // to tell the follower that the task ended
    $shared->progress = null;
    

    重要提示:这里,some_file.txt是存储任务共享数据的地方,因此,如果每个用户都有自己的任务,请不要犹豫使用“task_[user_id].txt”。并查看github上的自述文件以优化文件访问。

    • 进度在任务开始时设置为0,因此要做的第一件事是在运行任务之前检查此进度未设置为0。

    phptask-launch.php

    <?php
    
    require("Sync.php");
    $shared = new Sync("some_file.txt");
    
    if (is_null($shared->progress)) {
      exec("/usr/bin/php task.php > /dev/null 2>&1 &");
    }
    
      null
    <?php
    
    require("Sync.php");
    
    $total_stuffs = 200;
    $current_stuff = 0;
    
    $shared = new Sync("some_file.txt");
    
    // here is the magic: impossible to set the progression to 0 if an instance is running
    // ------------------
    $shared->lock();
    if (!is_null($shared->progress))
    {
        $shared->unlock();
        exit ;  
    }
    $shared->progress = 0;
    $shared->unlock();
    // ------------------
    
    while ($current_stuff < $total_stuffs) {
      $shared->progress = round($current_stuff * 100 / $total_stuffs, 2);
    
      // ... some stuff
      sleep(1);
    
      $current_stuff++;
    }
    
    // the task ended, no more progression
    $shared->progress = null;
    

    警告:如果您的任务崩溃,永远无法到达终点,您将永远无法再启动它。为了避免这种情况,您还可以将子级的getmypid()和一些time()存储在共享变量中,并在任务中添加超时逻辑。

    轮询表示每隔一段时间(例如,1秒、5秒或其他时间)向服务器请求进度信息。总之,客户机每N秒向服务器询问一次进度信息。

    • 在服务器端,我们需要编写处理程序以回答进度信息。

    phptask-follow.php

    <?php
    
    require("Sync.php");
    
    $shared = new Sync("some_file.txt");
    
    if ($shared->progress !== null) {
        echo $shared->progress;
    } else {
        echo "--"; // invalid value that will break polling
    }
    
      null
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
            <title>My Task!</title>
        </head>
        <body>
    
            <a id="run_task" href="#">Run task</a>
    
            <div id="task_progress">Progression: <span id="task_progress_pct">XX</span>%
    
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    
            <script type="text/javascript">
    
                $('#run_task').click(function(e) {
                    e.preventDefault();
    
                    <!-- not a good practice to run a long-running task this way but that's a sample -->
                    $.get('task-launch.php');
    
                    <!-- launches the polling business -->
                    setTimeout(function() {
                        getProgressionInformation();
                    }, 1000);
    
                });
    
                function getProgressionInformation() {
                    $.get('task-follow.php', function(progress) {
                        $('#task_progress_pct').html(progress);
                        if (progress !== '--') {
                            <!-- if the task has not finished, we restart the request after a 1000ms delay -->
                            setTimeout(function() {
                                getProgressionInformation();
                            }, 1000);
                        }
                    });
                }
    
                /* the task might be already running when the page loads */
                $(document).ready(function() {
                    getProgressionInformation();
                });
    
            </script>
    
        </body>
    </html>
    

    在我们的演示中:

    • 追随者变为:

    phptask-follow.php

    <?php
    
    require("Sync.php");
    
    $shared = new Sync("some_file.txt");
    
    if ($shared->progress !== null) {
        echo $shared->progress;
    }
    
      null
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
            <title>My Task!</title>
        </head>
        <body>
    
            <a
                href="#"
                id="run-task"
                class="domajax click"
                data-endpoint="task-launch.php"
                data-domajax-complete="#polling"
            >Run task</a>
    
            <div
                id="polling"
                data-endpoint="task-follow.php"
                data-delay="1000"
                data-output-not-empty="#task-progress-pct"
                data-domajax-not-empty=""
            ></div>
    
            <div id="task-progress">Progression: <span id="task-progress-pct">--</span>%
    
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
            <script src="//domajax.com/js/domajax/jquery.domajax.js"></script>
    
        </body>
    </html>
    

  •  类似资料:
    • 问题内容: 构建通知时,如何发出没有声音的通知?我正在构建通知,我的用户不喜欢它发出声音的事实。 如何将其更改为无声/无声? 我如何显示通知: 我尝试在Google上进行搜索,但我得到的唯一结果是如何播放声音,而不是不播放声音… 编辑 在某些人看来,它可能是重复的,但是在我的我无法找到指定默认值的替代方法,而此新方法称为setDefaults 问题答案: 删除的行。它不会播放声音,但是如果需要,您

    • 问题内容: 我正在尝试在HTML页面上显示一些JavaScript变量。我第一次使用它,但是当调用该函数时,它用于覆盖当前页面。 在四处搜寻之后,普遍的共识是人们对此不太喜欢。还有哪些其他选择? 我找到了一个建议使用的页面,但该页面写于2005年。 问题答案: 几乎是要走的路。以下是使用它的几种方法: HTML JavaScript 如果您只想更新I 的一部分,通常只需要添加一个类似或类的空元素,

    • 问题内容: 我想显示加载有进度条的ajax响应的用户百分比。有办法实现吗?现在,我只显示图像。 这是我的代码示例: HTML代码: 问题答案: 有两种显示真实百分比的方法。简短地… 一个 -老式的原生JavaScript或jQuery ajax,您也需要服务器支持,而另一个URL可以为您提供更新。而且您会间隔一定时间点击该URL。 两个 -HTML5浏览器中的现代本机JavaScript,支持 X

    • 我已经安装了Android SDK最新版本和Eclipse。但我也想试试Android Studio。 我看过这个和这个帖子,但是那些解决方案改变了Android Studio(一旦下载并安装)使用的SDK实例。我想要的不是下载另一个SDK,当我已经在我的机器上安装了它。

    • 问题内容: 示例问题: 实体: 用户包含姓名和朋友列表(用户参考) 博客文章包含标题,内容,日期和作者(用户) 需求: 我想要一个显示标题的页面以及指向用户朋友的最近10篇博客的链接。我还希望能够通过较旧的条目继续进行分页。 SQL解决方案: 因此在sql land中,它将类似于: 我能想到的GAE解决方案是: 加载用户,循环浏览好友列表并加载其最新博客帖子。最后合并所有博客文章以查找最新的10个

    • 我正在上一门Java课程,我们还没有正式学习if语句。我在学习,看到了这个问题: