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


How to design an AJAX interface to show progress bar based ona running script backend

我的问题是。

  1. 我有一个基于输入X输出XML的文件
  2. 我有另一个文件,它调用上述(1)文件10000次(我的意思是很多次)不同的数字X

当用户点击"Go"时,它应该遍历所有10000个x,并同时向他显示完成的进度。(hmm可能每10秒更新一次)。

我该怎么做?我需要创意。我知道如何AJAX和东西,但我的程序应该采取什么结构?

编辑

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

当我执行一个长脚本。它会在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);
    }

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

编辑3

好了,我终于找到解决办法了。而不是从php文件中寻找输出,我现在直接到日志中寻找它。

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

编辑:我对$_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
然后从数据库中读取文件/select,当通过ajax请求进度时。但与memcached相比,这不是一个很好的解决方案。

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


<罢工>

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

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

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

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