php和ajax:显示长脚本的进度

php和ajax:显示长脚本的进度,php,jquery,ajax,Php,Jquery,Ajax,我有php脚本,这可能需要相当多的时间(最多3-5分钟),所以我想通知用户它是如何进行的 我读了这篇文章,决定使用会话来保存有关工作进度的信息 因此,我有以下php说明: public function longScript() { $generatingProgressSession = new Zend_Session_Namespace('generating_progress'); $generatingProgressSession->unsetAll

我有php脚本,这可能需要相当多的时间(最多3-5分钟),所以我想通知用户它是如何进行的

我读了这篇文章,决定使用会话来保存有关工作进度的信息

因此,我有以下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)
因此,long-scripted是通过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 helper,所以这个函数的结果是json对象{'total':'somevalue','processed':'other value'}

是的,很可能长的脚本占用了整个服务器,而当时发出的任何其他请求都在等待轮到它们。此外,我建议您不要每10秒运行一次检查脚本,无论上一次检查是否完成,而是让检查脚本在完成后自行触发

以您的图像为例,请求处于挂起状态,而不是同时运行3个检查请求,您可以将它们链接起来,以便在任何时候只运行一个检查请求

您可以使用setTimeout()函数替换setInterval()函数,并在AJAX检查请求完成后重新初始化setTimeout()

您可以在此处粘贴“pathToCheckingStatusFunction”的PHP吗

另外,我注意到“PathToCheckStatusFunction”ajax函数没有数据类型:“json”。这可能会造成问题。您是否在任何地方使用$_POST['format']

我还建议在第一次检查完成后将检查链接到。如果你需要帮助,我可以发布一个解决方案

编辑、添加可能的解决方案:

我不确定使用Zend_名称空间是否是正确的方法。我建议使用session\u start()和session\u name()。从$\u会话中调用变量

示例文件1:

session_name('test');
session_start();
$_SESSION['percent'] = 0;

...stuff...

$_SESSION['percent'] = 90;
示例文件2(获取百分比):


很可能是由于会话锁定,以下调用未完成。当一个线程打开一个会话文件时,没有其他PHP线程可以打开同一个文件,因为在前一个线程释放该文件之前,该文件处于读/写锁定状态

或者您的服务器或浏览器正在限制并发请求,因此等待此请求完成

我的解决方案是要么分叉,要么以某种方式中断长时间运行的脚本。可能是对另一个脚本调用
exec
,并使用必需的参数,或者您认为可行的任何方式。将长时间运行的脚本拆分为单独的线程,并从当前线程返回,通知用户执行已经开始

第二部分是在某处记录脚本的进度。数据库、Memcache或文件都可以工作。只需在预先确定的位置设置一个值,后续调用就可以检查该值

并不是说“预先决定”对每个人都不应该是一样的。它应该是一个只有用户会话和工作人员知道的位置。

exec ('nohup php ...');

文件并将其发送到后台。您可以设置长时间运行的脚本在DB中插入单个值以显示其进度的点。现在,如果添加了新值,您可以每隔10秒或任何时间检查一次,并通知用户。根据您的环境,甚至可以在用户位于项目中的另一个页面时通知用户

我想了解为什么在对长php脚本的请求完成之前,这些检查进度的请求无法完成。我在ajax调用中添加了“dataType”属性,但它不起作用。此外,我还添加了用于检查状态的php函数,这样也许可以理解我更改“CheckingStatusFunction”的问题php代码在不使用会话的情况下返回预定义值,但仍然无法运行-等待长脚本完成。您知道如何检查浏览器或服务器是否阻止并发请求吗?如果设置了会话自动启动,则线程将自动尝试启动会话,从而阻止().我将我的长脚本更改为一个带sleep(10)命令的循环-因此它不能消耗所有内存和处理器资源,但仍然检查状态功能不工作。您知道服务器配置中是否有我应该为此任务设置的属性吗?脚本不太可能占用“整个”服务器,使其无法运行任何其他内容。除了数据库服务器上的大量SQL查询锁定表之外,我还没有遇到过这种情况。
exec ('nohup php ...');