PHP / Ajax轮询进度

时间:2013-01-28 19:14:09

标签: php ajax jquery

我试图在我的尝试中实现对PHP脚本循环的实时轮询而没有运气。以下是我到目前为止的情况:

表格提交:

$.ajax({
data: $(this).serialize(),
success: showResponse,
url: 'process.php',
type: 'post'
});

function showResponse(){
$.ajax({
type: "GET",
url: "progress.php",
cache: false,
success: function(data) {
var response = $.parseJSON(data);
if (response.processing === true) {
console.log("Current Item: " + response.currentItem +
"Total Items: " + response.totalItems +
 "Percent Complete: " + response.percentComplete);
setTimeout(checkProgress, 1000);
});
}

在process.php脚本中:

session_start();
echo json_encode(array("processing" => true));
$totalItems = 10000000;
$_SESSION['totalItems'] = $totalItems;
$_SESSION['processing'] = true;
$_SESSION['error'] = false;
for ($i=0; $i <= $totalItems; $i++) {
$_SESSION['currentItem'] = $i;
$_SESSION['percentComplete'] = round(($i / $totalItems * 100));
}

在进度php脚本中:

session_start();
echo json_encode(array(
"processing" => $_SESSION['processing'],
"error" => $_SESSION['error'],
"currentItem" => $_SESSION['currentItem'],
"totalItems" => $_SESSION['totalItems'],
"percentComplete" => $_SESSION['percentComplete']
)
);

不知道我在哪里出错了,但是一旦它达到100%完成就会完成循环。任何建议将不胜感激!

修改的 我将上面的内容改为在process.php中使用apc:

apc_store('totalItems', $totalItems);
apc_store('processing', true);
apc_store('error', false);
apc_store('currentItem', $i);
apc_store('percentComplete', round(($i / $totalItems * 100)));

在progress.php中:

echo json_encode(array(
"processing" => apc_fetch('processing'),
"error" => apc_fetch('error'),
"currentItem" => apc_fetch('currentItem'),
"totalItems" => apc_fetch('totalItems'),
"percentComplete" => apc_fetch('percentComplete')
    )
);

我仍然没有按照我想要的方式正常工作,我做错了什么?它只显示错误值,直到脚本完成并显示100%,就像之前使用的会话一样。有什么想法吗?

1 个答案:

答案 0 :(得分:5)

会话信息是一种只能专门使用的资源,您还没有考虑到这一点。

具体来说,在默认设置下session_start会导致PHP获取包含会话数据的文件的独占锁。在脚本退出或调用session_write_close之前,此文件未解锁。

在您的示例中,process.php获取锁定并开始工作。在此期间,progress.php尝试session_start()而不能(由于锁定)。在满足进度信息请求之前,需要为process.php完成并退出(从而释放锁定)足够的时间。

您可以立即生效的一个小改动是从您的工作循环中调用session_write_closesession_start

for ($i=0; $i <= $totalItems; $i++) {
    session_start();
    $_SESSION['currentItem'] = $i;
    $_SESSION['percentComplete'] = round(($i / $totalItems * 100));
    session_write_close();
}

这将允许两个脚本轮流锁定会话存储文件,因此您将看到按预期工作的内容。但是,性能会 tank (这是处理会话存储文件的一种非常不礼貌的方式)。

如果你需要在现实世界中做这样的事情,有必要利用会话数据以外的东西来实现PHP脚本之间的信息交换(例如像APC或memcached这样的内存缓存)。