PHP/Ajax轮询进度

Bri*_*ian 1 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);
});
}
Run Code Online (Sandbox Code Playgroud)

在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));
}
Run Code Online (Sandbox Code Playgroud)

在进度php脚本中:

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

我不知道我在哪里出错了,但它完成后只需完成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)));
Run Code Online (Sandbox Code Playgroud)

并在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')
    )
);
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*Jon 5

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

具体来说,在默认设置下,session_startPHP会获取包含会话数据的文件的独占锁定.在脚本退出或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();
}
Run Code Online (Sandbox Code Playgroud)

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

如果你有需要做这样的事情在现实世界中,有必要利用其他的东西比会话数据,使PHP脚本之间的这种交流的信息(例如在内存中缓存像APC或memcached的).