两个同时的 AJAX 请求不会并行运行

Posted

技术标签:

【中文标题】两个同时的 AJAX 请求不会并行运行【英文标题】:Two simultaneous AJAX requests won't run in parallel 【发布时间】:2013-03-19 04:05:25 【问题描述】:

我遇到了两个同时运行的 AJAX 请求的问题。我有一个将数据导出到 XSLX 的 php 脚本。这个操作需要很多时间,所以我试图向用户展示进度。我正在使用 AJAX 和数据库方法。实际上,我很确定它曾经可以工作,但我不知道为什么,它不再在任何浏览器中工作。新浏览器有什么变化吗?

$(document).ready(function() 

        $("#progressbar").progressbar();

        $.ajax(
            type: "POST",
            url: "$BASE_URL/export/project/ajaxExport",
            data: "type=$type&progressUid=$progressUid" // unique ID I'm using to track progress from database
        ).done(function(data) 
            $("#progressbar-box").hide();
            clearInterval(progressInterval);
        );

        progressInterval = setInterval(function() 
            $.ajax(
                type: "POST",
                url: "$BASE_URL/ajax/progressShow",
                data: "statusId=$progressUid" // the same uinque ID
            ).done(function(data) 
                data = jQuery.parseJSON(data);
                $("#progressbar").progressbar( value: parseInt(data.progress) );
                if (data.title)  $("#progressbar-title").text(data.title); 
            );
        , 500);

    );
数据库中的进度正在正确更新 JS 计时器正在尝试获取进度,我可以在控制台中看到它,但是所有这些请求都在加载第一个脚本的整个持续时间,一旦脚本结束,这些 ajax 进度调用就会被加载

那么,为什么第二个 AJAX 调用要等待第一个调用完成?

【问题讨论】:

一些 PHP Web 服务器配置只允许每个会话一个连接同时运行。因此,如果您正在使用会话,请在您 (a) 开始会话,然后 (b) 休眠 60 秒的页面中尝试进行实验。然后尝试在同一个浏览器中加载该页面的多个实例 - 它们可能会一个接一个地加载。 你最近更新了jQuery版本吗? 另外,一般来说,一个以上的 AJAX 操作并不是最佳实践,因为过多的 HTTP 调用会浪费时间。你能把它们合并成一个,然后在一个 JSON 字符串中返回几个结果吗? 如果您使用服务器端会话,PHP 默认会在请求处于活动状态时锁定会话文件,这意味着您在任何时候都不能有多个未完成的请求处于活动状态。 马克 B 你是对的!这是会话问题。我正在使用 codeigniter 会话库,但我最近将其更改为本机会话库,我没有意识到这可能是问题所在。谢谢。您可以将其发布为答案,以便我将其标记为已接受。 【参考方案1】:

听起来像是会话阻塞问题

默认情况下,PHP 将其会话数据写入文件。当您使用 session_start() 启动会话时,它会打开文件进行写入并锁定它以防止并发编辑。这意味着对于使用会话通过 PHP 脚本的每个请求,都必须等待第一个会话完成文件。

解决此问题的方法是将 PHP 会话更改为不使用文件或关闭会话,如下所示:

<?php
    session_start(); // starting the session

    $_SESSION['foo'] = 'bar'; // Write data to the session if you want to

    session_write_close(); // close the session file and release the lock

    echo $_SESSION['foo']; // You can still read from the session.

【讨论】:

是的卡伦巴。不是 PHP 会话的粉丝,但使用 Symfony 进行开发,充分利用了它们。有道理,但永远不会猜到。好帮手!【参考方案2】:

经过一番折腾,我发现了一种 other 可以发生这些非并行 AJAX 请求的方式,完全独立于 PHP 会话处理...所以我将其发布在这里仅适用于通过 Google 遇到同样问题的任何人。

XDebug 可以导致这种情况,如果 Zend Debugger 也可以,我不会感到惊讶。

就我而言,我有:

XDebug 安装在我的本地 LAMP 堆栈上 xdebug.remote_autostart 已启用 我的 IDE 接受入站调试器连接,即使没有处于活动状态的断点

这导致我所有的 AJAX 测试都按顺序运行,无论如何。回想起来,强制顺序处理很有意义(从调试的角度来看),但我根本没有注意到我的 IDE 仍在幕后交互。

告诉 IDE 完全停止监听后,并行运行恢复,我能够重现我一直在寻找的竞争条件。

【讨论】:

【参考方案3】:

请注意,session_write_close()(answer of chrislondon) 可能无法解决问题,如果您启用了输出缓冲(PHP 7+ 中的默认设置)。您必须在php.ini中设置output_buffering = Off,否则会话将无法正确关闭。

【讨论】:

【参考方案4】:

使用 API 时,您有时需要向不同的端点发出多个 AJAX 请求。您可以使用 jQuery 的 $.when() 函数并行请求数据,而不是等待一个请求完成后再发出下一个请求:

Run multiple AJAX requests in parallel

【讨论】:

【参考方案5】:

a.php 生成一个主 html 页面,其中包含对 b.phpc.php 的两个同时 AJAX 调用。为了 b.phpc.php 共享会话变量,会话变量必须在第一次 AJAX 调用之前存在。如果这是真的,a.phpb.php 可以更改会话变量的值并查看彼此的值。因此,在生成 HTML 页面时使用 a.php 创建会话变量。至少 Rogers 共享虚拟主机是这样工作的。

【讨论】:

【参考方案6】:

你也可以设置

async: true,

【讨论】:

这是给我用的 ExtJs 的?

以上是关于两个同时的 AJAX 请求不会并行运行的主要内容,如果未能解决你的问题,请参考以下文章

Azure DevOps YAML并行运行未排队

并行执行多个 AJAX 请求,并在所有请求完成后运行一个函数

当两个 Ajax 请求被并行调用时,我看到多个加载掩码

RestKit 网络限制在并行请求运行时阻止其他调用

多线程

并发和并行