javascript - Ajax 调用 DURING 另一个 Ajax 调用来接收服务器的任务计算状态并将其作为进度条显示给客户端

标签 javascript php jquery ajax yii2

我试图弄清楚是否有机会通过多个(时间间隔的)ajax 调用接收任务的完成状态(通过 ajax 调用触发)。 基本上,在执行可能需要很长时间的事情期间,我想填充一些变量并在询问时返回它的值。

服务器代码如下所示:

function setTask($total,$current){
    $this->task['total'] = $total;
    $this->task['current'] = $current;
}

function setEmptyTask(){
    $this->task = [];
}

function getTaskPercentage(){
    return ($this->task['current'] * 100) / $this->task['total'];
}

function actionGetTask(){
    if (Yii::$app->request->isAjax) {

        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        return [
            'percentage' => $this->getTaskPercentage(),
        ];
    }
}

假设我处于 for 循环中,并且我知道迭代了多少次:

function actionExportAll(){
    $size = sizeof($array);
    $c = 0;
    foreach($array as $a){
        // do something that takes relatively long
        $this->setTask($size,$c++);
    }
}

在客户端我有这个:

function exportAll(){
    var intervalId = setInterval(function(){
        $.ajax({
            url: '/get-task',
            type: 'post',
            success: function(data){
                console.log(data);
            }
        });
    },3000);

    $.ajax({
        url: '/export-all',
        type: 'post',
        success: function(data){
            clearInterval(intervalId); // cancel setInterval
            // ..
        }
    });
}

这看起来可行,除了 setInterval 函数中完成的 ajax 调用“export-all”完成并进入成功回调之后完成这一事实。 在这个逻辑中我肯定缺少一些东西。 谢谢

最佳答案

问题可能出在 session 中。

让我们看看发生了什么。

  1. /export-all 的请求由浏览器发送。
  2. 服务器上的应用调用 session_start() 打开 session 文件并锁定对其的访问。
  3. 应用开始执行昂贵的操作。
  4. 在浏览器中,设置的时间间隔过去后,浏览器将请求发送到 /get-task
  5. 服务器上的应用尝试处理 /get-task 请求并调用 session_start()。它被阻止,必须等待 /export-all 请求完成。
  6. /export-all 的昂贵操作已完成,响应已发送到浏览器。
  7. session 文件已解锁,/get-task 请求最终可以继续通过 session_start()。同时浏览器已收到 /export-all 响应并为其执行成功回调。
  8. /get-task 请求已完成,响应已发送到浏览器。
  9. 浏览器收到 /get-task 响应并执行其成功回调。

处理它的最佳方法是避免直接从用户浏览器执行的请求运行昂贵的任务。 您的 export-all 操作应该只计划执行任务。然后任务本身可以由某些 cron 操作或后台的某些工作人员执行。 /get-task 可以检查其进度并在任务完成时触发最终操作。

您应该看看yiisoft/yii2-queue扩大。此扩展允许您创建作业,将它们排入队列,并通过 cron 任务或运行一个监听任务并在任务到来时执行它们的守护进程来运行队列中的作业。

关于javascript - Ajax 调用 DURING 另一个 Ajax 调用来接收服务器的任务计算状态并将其作为进度条显示给客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59305943/

相关文章:

javascript - Chrome 扩展内容脚本中的 polymer

javascript - NVD3.js 在鼠标悬停事件处突出显示图形点

php - Laravel 框架中的自定义函数原始查询

jQuery ajax 和 CORS 不工作

JavaScript代码 'window.location'执行onclick

javascript - 如何使用css使高度等于宽度

javascript - 当前元素作为其事件函数参数

php - 需要以某种不同的方式获取索引为零处的数组

php - 使用数据库信息作为下拉列表选项

javascript - 在页面加载时清除/重新应用表排序器过滤