Два одновременных запроса AJAX не будут выполняться параллельно

У меня проблема с двумя одновременными запросами AJAX. У меня есть PHP script, который экспортирует данные в 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 пытается получить прогресс, я вижу его на консоли, но все эти запросы загружают всю длительность первого script, как только заканчивается script, эти вызовы прогресса ajax загруженный

Итак, почему второй вызов AJAX ожидает завершения первого?

Ответ 1

Звучит как проблема блокировки сеанса

По умолчанию PHP записывает свои данные сеанса в файл. Когда вы начинаете сеанс с session_start(), он открывает файл для записи и блокирует его для предотвращения одновременных изменений. Это означает, что для каждого запроса, проходящего через PHP script с использованием сеанса, необходимо дождаться, когда первый сеанс будет выполнен с файлом.

Чтобы исправить это, нужно изменить сеансы 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.

Ответ 2

После небольшого стрижки волос я нашел один другой способ, которым могут следовать эти непараллельные запросы AJAX, полностью независимые от обработки сеансов PHP... Поэтому я размещаю его здесь только для тех, кто попадает сюда через Google с той же проблемой.

XDebug может вызвать это, и я не удивлюсь, если Zend Debugger тоже может.

В моем случае у меня было:

  • XDebug установлен в локальном стеке LAMP
  • xdebug.remote_autostart включено
  • Моя IDE принимает входящие соединения отладчика, даже если никакие точки останова не были активны.

Это привело к тому, что все мои тесты AJAX выполнялись последовательно, несмотря ни на что. Оглядываясь назад, это имеет большое значение (с точки зрения отладки вещей) для принудительной последовательной обработки, но я просто не заметил, что моя среда IDE все еще взаимодействует за кадром.

После того, как среда IDE перестала полностью прослушиваться, возобновились параллельные прогоны, и я смог воспроизвести состояние гонки, которое я искал.

Ответ 3

Помните, что session_write_close() [ответ chrislondon] может не решить проблему, если вы включили буферизацию вывода (по умолчанию в PHP 7+). Вы должны установить output_buffering = Off в php.ini, иначе сеанс не будет закрыт правильно.

Ответ 4

Вы также можете установить

async: true,

Ответ 5

При работе с API-интерфейсами вам иногда необходимо выдать несколько запросов AJAX для разных конечных точек. Вместо того, чтобы ждать завершения одного запроса перед выпуском следующего, вы можете ускорить работу с jQuery, запросив данные параллельно, используя функцию jQuery $.when():

Параллельно запускайте несколько запросов AJAX

Ответ 6

a.php создает основную HTML-страницу, содержащую два одновременных вызова AJAX для b.php и c.php. Для того чтобы b.php и c.php делились переменными сеанса, переменные сеанса должны существовать ПЕРЕД первым вызовом AJAX. Если это так, a.php и b.php могут изменять значение переменных сеанса и видеть значения друг друга. Поэтому создайте переменные сеанса с помощью a.php при создании HTML-страницы. (По крайней мере, как это работает с общим хостингом Роджерса.)