我有PHP脚本,可能需要很长时间(最多3-5分钟),所以我想通知用户它是怎么回事。
我读了这个question并决定使用session来保存有关工作进度的信息。
所以,我在php中有以下说明:
public function longScript()
{
$generatingProgressSession = new Zend_Session_Namespace('generating_progress');
$generatingProgressSession->unsetAll();
....
$generatingProgressSession->total = $productsNumber;
...
$processedProducts = 0;
foreach($models as $model){
//Do some processing
$processedProducts++;
$generatingProgressSession->processed = $processedProducts;
}
}
我有简单的脚本从会话中获取数据(总数和已处理项目数),以json格式返回它们。
所以,这里是用于调用长脚本的js代码:
$.ajax({
url: 'pathToLongScript',
data: {fileId: fileId, format: 'json'},
dataType: 'json',
success: function(data){
if(data.success){
if(typeof successCallback == "function")
successCallback(data);
}
}
});
//Start checking progress functionality
var checkingGenerationProgress = setInterval(function(){
$.ajax({
url: 'pathToCheckingStatusFunction',
data: {format: 'json'},
success: function(data){
console.log("Processed "+data.processed+" items of "+data.total);
if(data.processed == data.total){
clearInterval(checkingGenerationProgress);
}
}
});
}, 10000)
因此,长脚本通过ajax调用。然后在10秒后检查脚本被调用一次,20秒后 - 第二次等。
问题是在主长脚本完成之前,没有任何检查脚本的请求完成。那么,这意味着什么?那个长脚本占用了太多资源,服务器无法处理任何其他请求?或者我有一些错误的ajax参数?
见图片:
----------- UPD
这是一个用于检查状态的php函数:
public function checkGenerationProgressAction()
{
$generatingProgressSession = new Zend_Session_Namespace('generating_progress');
$this->view->total = $generatingProgressSession->total;
$this->view->processed = $generatingProgressSession->processed;
}
我在这里使用ZF1 ActionContext助手,因此这个函数的结果是json对象{'total':'somevalue','processed':'another value'}
答案 0 :(得分:1)
我
exec ('nohup php ...');
文件并将其发送到后台。您可以设置长时间运行的脚本在DB中插入单个值以显示其进度的点。现在,如果添加了新值,您可以每隔十秒或任何秒检查并通知用户。根据您的环境,甚至可以在项目中的其他页面上通知用户。
答案 1 :(得分:0)
是的,长脚本可能会占用整个服务器,并且在那段时间内发出的任何其他请求都在等待轮到他们。另外,我建议你不要每隔10秒运行一次检查脚本,无论前一次检查是否完成,而是让检查脚本在完成后自动触发。
以请求待处理的图像为例,而不是同时运行3个检查请求,您可以链接它们,以便在任何时候只运行一个检查请求。
您可以通过使用setTimeout()函数替换setInterval()函数并在AJAX检查请求完成后重新初始化setTimeout()来执行此操作
答案 2 :(得分:0)
你能在这里粘贴“pathToCheckingStatusFunction”的PHP吗?
另外,我注意到“pathToCheckingStatusFunction”ajax函数没有dataType:“json”。这可能会导致问题。你在任何地方使用$ _POST ['format']吗?
我还建议在第一次检查完成后将检查链接起来。如果您需要帮助,我可以发布解决方案。
编辑,添加可能的解决方案:
我不确定使用Zend_namespace是正确的方法。我建议使用session_start()和session_name()。从$ _SESSION中调用变量。
示例文件1:
session_name('test');
session_start();
$_SESSION['percent'] = 0;
...stuff...
$_SESSION['percent'] = 90;
示例文件2(获取百分比):
session_name('test');
session_start();
echo $_SESSION['percent'];
答案 3 :(得分:0)
最有可能的是,由于会话锁定,以下呼叫未完成。当一个线程打开一个会话文件时,没有其他PHP线程可以打开同一个文件,因为它是读/写锁定的,直到前一个线程允许它为止。
或者服务器或浏览器限制并发请求,因此等待这个请求完成。
我的解决方案是以某种方式解析或打破长时间运行的脚本。也许用exec
调用具有必需参数的其他脚本,或者您认为可行的任何方式。将长时间运行的脚本分解为一个单独的线程并从当前线程返回,通知用户执行已经开始。
第二部分是在某处记录脚本的进度。数据库,Memcache或文件可以工作。只需在后续呼叫可以检查的预定位置设置一个值。
不是"预先确定"对每个人来说都不应该是一样的。它应该是只有用户会话和工作人员知道的位置。