1

我正在尝试实现 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%,就像之前的会话使用一样。有任何想法吗?

4

1 回答 1

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();
}

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

如果您需要在现实世界中执行类似的操作,则有必要利用会话数据以外的其他内容来启用 PHP 脚本之间的这种信息交换(例如 APC 或 memcached 等内存缓存)。

于 2013-01-28T19:21:20.877 回答