PHP / Ajax轮询进度

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

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

具体来说,在默认设置下, 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(); } 

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

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