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

У меня проблема с двумя одновременными запросами 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 ждет завершения первого?

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

По умолчанию 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. 

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

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

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

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

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

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

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

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

 async: true, 

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

Запуск нескольких запросов AJAX параллельно

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