如何设计一个AJAX界面来显示基于正在运行的脚本后端的进度条

时间:2011-07-31 16:38:55

标签: php javascript xml ajax multiprocessing

好的,这是我的问题。

  1. 我有一个基于输入X输出XML的文件
  2. 我有另一个文件调用上面的(1)文件,其中10000(我的意思是很多次),不同的数字为X
  3. 当用户点击“Go”时,它应该遍历所有10000 X并同时向他显示完成了多少次的进度。 (嗯可能每10秒更新一次)。

    我该怎么做?我需要点子。我知道如何使用AJAX和东西,但我的程序应该采用哪种结构?

    修改

    因此,根据下面给出的答案,我确实将输出存储在会话变量中。然后输出答案。发生的事情是:

    当我执行一个loong脚本。它会在1分钟内执行。但同时如果我打开(在新窗口中)只输出我的SESSION变量的文件,那么它不会输出第一个脚本运行。这与我想要的完全相反。问题出在这里?是我的系统/服务器没有处理多个请求或什么?

    编辑2

    我使用文件方法: 阅读我想要的内容

    > <?php include_once '../includeTop.php'; echo
    > util::readFromLog("../../Files/progressData.tmp"); ?>
    

    并在另一个脚本中

    $processed ++;
    util::writeToLog($dir.'/progressData.tmp', "Files processed: $processed");
    

    其中的功能是:

       public static function writeToLog($file,$data) {
            $f = fopen($file,"w");
            fwrite($f, $data);
            fclose($f);
        }
        public static function readFromLog($file) {
            return file_get_contents($file);
        }
    

    但仍然存在相同的问题:(。我可以手动查看文件gettin更新如1,2,3等。但是当我从php运行我的脚本时它只是等待直到我的原始脚本输出。

    编辑3

    好的,我终于找到了解决方案。不是从php文件中寻找输出,而是直接转到日志并寻找它。

2 个答案:

答案 0 :(得分:3)

将进度(即你在第二个文件中有多远)直接从后台作业放入memcached,然后在javascript应用程序请求时传递该值(由计时器触发,只要你没有达到100%)。您唯一需要弄清楚的是如何将某种“事务ID”传递给后台作业和javascript端,因此它们访问memcached中的相同键。

答案 1 :(得分:1)

编辑:我对$_SESSION错了。它不会异步更新,即在脚本完成之前无法访问存储在其中的值。糟糕。

因此,需要将进度存储在异步更新的内容中:内存(如pyroscope建议,哪些仍是最佳解决方案),文件或数据库。

换句话说,不应使用$_SESSION来存储值,而应将其存储在memcached中,存储在文件中或数据库中。

即。使用数据库

$progress = 0;
mysql_query("INSERT INTO `progress` (`id`, `progress`) VALUES ($uid, $progress)");
# loop starts
    # processing...
    $progress += $some_increment;
    mysql_query("UPDATE `progress` SET `progress`=$progress WHERE `id`=$uid");
# loop ends

或使用文件

$progress = 0;
file_put_contents("/path/to/progress_files/$uid", $progress);
# loop starts
    # processing...
    $progress += $some_increment;
    file_put_contents("/path/to/progress_files/$uid", $progress);
# loop ends

然后在通过ajax请求进度时从数据库中读取文件/ select。但与memcached相比,它不是一个漂亮的解决方案。

另外,请记住在完成所有操作后删除文件/数据库行。


<击>

<击>

您可以将进度放在$_SESSION变量中(您需要一个唯一的名称),并在进程运行时更新它。同时,你的ajax请求只是以特定的间隔获得该变量

function heavy_process($input, $uid) {
    $_SESSION[$uid] = 0;
    # loop begins
        # processing...
        $_SESSION[$uid] += $some_increment;
    # loop ends
}

然后有一个url,当通过ajax请求时,它会简单地吐出$_SESSION[$uid]值。然后使用返回的值更新进度条。使用类似sha1(microtime())的内容来创建$ uid

编辑:pyroscope的解决方案在技术上更好,但是如果你没有带memcached的服务器或能够运行后台进程,你可以使用$_SESSION代替