如何显示加载百分比以及如何在没有javascript的情况下执行此操作? [英] How to display loading percentage and how to do it without javascript?

查看:145
本文介绍了如何显示加载百分比以及如何在没有javascript的情况下执行此操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在PHP
中创建类似于加载器的东西,所以我使用了这段代码:

 <? php 
$ x = 1;
while($ x< = 100){
echo正在加载:$ x%< br>;
$ x ++;
}
?>

这样它就会显示从Loading 1%到Loading 100%。
但是这会导致所有出现的一个在新线出现后不会消失。因此,我想知道如何使新行显示并且旧的消失,并且在页面加载后开始,因此用户将能够看到实际加载的加载器从1%到100%。



更新:我知道我应该使用 JS 和/或 Ajax 来实现它,我只是想知道如果有办法在PHP中也这样做:)

解决方案

遵循长时间运行的任务很常见但不容易第一次实施。这是一个完整的例子。




(但始终安全地将其内容同步到文件中。



只需下载 src / Sync.php 并通过以下方式更改上面的task.php:



PHP task.php

 <?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);

// ...一些东西
sleep(1);

$ current_stuff ++;
}

//告诉关注者任务结束
$ shared-> progress = null;

重要提示:此处, some_file.txt 是存储任务共享数据的位置,因此如果每个用户都有自己的任务,请不要犹豫使用task_ [user_id] .txt。并查看,旨在做没有javascript的ajax(事实上) ,插件本身是jQuery,但使用它不需要JavaScript代码),通过组合选项,你可以进行轮询。



在我们的演示中:




  • 关注者变为:



PHP task-follow.php

 <?php 

require(Sync.php );

$ shared = new Sync(some_file.txt);

if($ shared-> progress!== null){
echo $ shared-> progress;
}




  • UI来源变为:



HTML ui-domajax.html

 <!DOCTYPE html> 
< html lang =en>
< head>
< meta http-equiv =content-typecontent =text / html; charset = utf-8/>
< title>我的任务!< / title>
< / head>
< body>

< a
href =#
id =run-task
class =domajax click
data-endpoint = task-launch.php
data-domajax-complete =#polling
>运行任务< / 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>进展:< 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>

如您所见,此代码中根本没有可见的javascript。干净不是吗?



domajax的网站上提供了其他例子,查看演示窗格中的轻松管理进度条选项卡。所有选项都有详细记录以供详细说明。


I want to make something similar to loaders in PHP so I used this code:

<?php 
$x=1;
while($x<=100) {
   echo "Loading: $x %<br>";
   $x++;
}   
?>

So that it would display from "Loading 1%" to "Loading 100%". But this will result in all appearing one at a time without disappearing after the new line appears. So I want to know how to make the new line appear and the old disappear and this starts after the page loads, so the user will be able to watch a loader actually loading from 1% to 100%.

UPDATE: I know I should use JS and/or Ajax to achieve it, I just wanted to know if there's a way to also do it in PHP :)

解决方案

To follow long-running tasks is common but not really easy to implement the first time. Here is a complete example.

(a sample of long-running task in a Sellermania's product)

Context

The task

Imagine you currently have the following task, and want to display a progress bar to your visitors.

PHP task.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++;
  }

The UI

Your beautiful UI looks like this:

HTML ui.html

<!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>

The launcher

We need to launch the task in background, in order to make this demonstration relevant. So, this php script will be called asynchronously when clicking "run", and will execute the task above in background.

PHP task-launch.php

<?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 &");


Problems

There are 3 problems here:

  1. you can run the task more than once by clicking several times the run button, how to avoid several tasks in the background at the same time?

  2. the task is ran at server side, so we need to do something to access the server and ask for progression information.

  3. and when we will be connected to the server side, the $progress variable is unavailable for reading, because it is stored within the context of the task.php running instance.


Solutions

Store progression information into something readable from outside

Usually, progression information are stored into a database, or a file, or whatever that can be writtable by a program (your task actaully), and readable by another (your ui where progression should be displayed).

I developped a class for sharing data within several php applications (available on github here), it works about the same way as stdClass but always securely synchronize its contents into a file.

Just download src/Sync.php and change the task.php above by:

PHP task.php

<?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;

Important note: here, some_file.txt is where are stored your task's shared data, so don't hesitate to use "task_[user_id].txt" for example if each user has its own task. And look at the readme on github to optimize file access.

Use the synchronized variable to protect the task launcher

  • The progression is set to 0 at the beginning of the task, so the first thing to do is to check, before running the task, that this progression is not set to 0.

PHP task-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 &");
}

  • If the run button is clicked twice very quickly, we can still have 2 instances of the task. To handle this case, we need to simulate a mutex, in a word, make the variable only available to the current application to do some stuff - other applications will stay sleeping until the shared variable is unlocked.

PHP task.php

<?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;

Warning: if your task crashes and never reach the end, you'll never be able to launch it anymore. To avoid such cases, you can also store the child's getmypid() and some time() stuffs inside your shared variable, and add a timeout logic in your task.

Use polling to ask the server progression information

Polling stands for asking for progression information to the server every lapse of time (such as, 1 sec, 5 secs or whatever). In a word, client asks progression information to the server every N secs.

  • at server-side, we need to code the handler to answer the progression information.

PHP task-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
}

  • at client-side, we need to code the "asking progression information to the server" business

HTML ui-polling.html

<!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>


With a minimum of JavaScript ?

I also developed a jquery plugin, domajax, intended to do "ajax without javascript" (in fact, the plugin itself is in jQuery, but using it do not require JavaScript code), and by combining options you can do polling.

In our demonstration:

  • the follower becomes:

PHP task-follow.php

<?php

require("Sync.php");

$shared = new Sync("some_file.txt");

if ($shared->progress !== null) {
    echo $shared->progress;
}

  • the UI source becomes:

HTML ui-domajax.html

<!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>

As you can see, there is no visible javascript at all in this code. Clean isn't it?

Other examples are available on domajax's website, look at the "Manage progress bars easily" tab in the demo pane. All options are heavily documented for details.

这篇关于如何显示加载百分比以及如何在没有javascript的情况下执行此操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆