12

我遇到了两个同时运行的 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 调用要等待第一个完成呢?

4

6 回答 6

38

听起来像是会话阻塞问题

默认情况下,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.
于 2013-03-28T22:07:56.453 回答
2

经过一番拉扯,我发现了一种方式可以发生这些非并行 AJAX 请求,完全独立于 PHP 会话处理......所以我在这里发布它只是为了任何通过谷歌到达这里的人都一样问题。

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

就我而言,我有:

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

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

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

于 2013-11-15T22:00:45.100 回答
2

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

于 2017-01-11T15:47:57.553 回答
0

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

并行运行多个 AJAX 请求

于 2014-03-11T06:29:36.923 回答
0

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

于 2015-12-23T02:45:14.990 回答
-1

你也可以设置

async: true,
于 2013-07-02T17:21:00.483 回答