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_close
和session_start
:
for ($i=0; $i <= $totalItems; $i++) { session_start(); $_SESSION['currentItem'] = $i; $_SESSION['percentComplete'] = round(($i / $totalItems * 100)); session_write_close(); }
这将允许两个脚本轮流锁定会话存储文件,因此您将看到事情按预期工作。 但是,性能会下降 (这是处理会话存储文件的一种非常不礼貌的方式)。
如果你需要在现实世界中做这样的事情,那么有必要利用会话数据以外的东西来实现PHP脚本之间的信息交换(例如内存缓存,如APC或memcached)。