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

时间:2013-03-28 16:00:10

标签: php ajax progress-bar simultaneous

我遇到两个同时运行的AJAX请求的问题。我有一个PHP脚本,它将数据导出到XSLX。此操作需要花费大量时间,因此我正在尝试向用户显示进度。我正在使用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调用等待第一个完成呢?

6 个答案:

答案 0 :(得分:31)

听起来像会话阻塞问题

默认情况下,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.

答案 1 :(得分:2)

经过一段时间的努力,我找到了一种其他方式,这些非并行的AJAX请求可以发生,完全独立于PHP会话处理...所以我在这里发布它只是对于那些通过谷歌遇到同样问题的人来说。

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

在我的情况下,我有:

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

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

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

答案 2 :(得分:1)

请注意,如果已启用输出缓冲(默认情况下为PHP 7+),则session_write_close()[chrislondon的回答]可能无法解决问题。你必须在php.ini中设置output_buffering = Off,否则会话不会被正确关闭。

答案 3 :(得分:0)

使用API​​时,有时需要向不同的端点发出多个AJAX请求。不是在发出下一个请求之前等待一个请求完成,而是通过使用jQuery的$ .when()函数并行请求数据来加快jQuery的速度:

Run multiple AJAX requests in parallel

答案 4 :(得分:0)

a.php生成一个主HTML页面,其中包含对b.php和c.php的两个同时AJAX调用。为了使b.php和c.php共享会话变量,会话变量必须在第一次AJAX调用之前存在。如果这是真的,a.php和b.php可以更改会话变量的值并查看彼此的值。因此,在生成HTML页面时使用a.php创建会话变量。 (至少它是如何与Rogers共享网络托管一起工作的。)

答案 5 :(得分:-1)

你也可以设置

async: true,