Не ожидая ответа от запроса AJAX

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

Итак, порядок в этом.

  • Я на сайте www.xyz.com
  • У меня есть обработчик jQuery, который запускает запрос AJAX к blah.php
  • blah.php запускается
  • Я скоро поеду на сайт www.abc.com, не дожидаясь ответа от blah.php

Что происходит с blah.php? Продолжается ли исполнение? Он остановился? Я имею в виду, что у него не было шанса ответить так …

Это может зависеть от конфигурации вашего сервера, но в целом сценарий будет продолжать выполняться, несмотря на закрытое HTTP-соединение .

Я тестировал это с Apache 2 + PHP 5 как mod_php . Я бы ожидал подобного поведения с PHP как CGI и с другими веб-серверами, но не знаю наверняка.

Лучший способ определить для определенной конфигурации, как @tdammers предлагает: настроить тестовый сценарий примерно так: следить за журналом.

<?php error_log('Test script started.'); for ($i = 1; $i < 13; $i++) { sleep(10); error_log('Test script got to ' . (10 * $i) . ' seconds.'); } error_log('Test script got to the end.'); ?> 

Получите доступ к этому скрипту (на /test.php или что-то еще), прежде чем вы получите какие-либо результаты, нажмите «остановить» в своем браузере. Это эквивалентно навигации до вашего XHR. Вы даже можете использовать его как цель XHR и перемещаться.

Затем проверьте свой журнал ошибок: вы должны начать, а затем сообщения каждые 10 секунд в течение двух минут и с конца. Вы можете изменить, как высокий $i получает, чтобы ваш скрипт достиг своего ожидаемого максимального времени выполнения, если вы тоже хотите его проверить.

Вам не нужно использовать error_log() – вы можете записать в файл или сделать некоторые другие постоянные изменения на сервере, которые можно проверить, не открывая соединение клиента.

Время выполнения скрипта может прекратиться до этого из-за директивы max_execution_time php.ini, но в любом случае это должно отличаться от того, когда веб-сервер отключается.

Попробуйте ignore_user_abort (true);

 ignore_user_abort(true); 

он не должен прерывать выполнение кода

Вы можете проверить ответы на этот вопрос . В основном, когда вы делаете свой вызов ajax функции php, которая вызывает функцию exec() как показано в ответах на этот вопрос, вы получите ответ ajax почти сразу, так как ваша php-функция фактически не нуждается в обработке чего-либо. Таким образом, не важно, покидает ли пользователь страницу. Вот небольшой пример:

ajax-вызов в html-файле: $.ajax({url: 'blah.php'});

Файл blah.php: exec('bash -c "exec nohup setsid php really_slow_script.php > /dev/null 2>&1 &"');

И затем, наконец, в файле really_slow_script.php, просто укажите фактический код, который вы хотите запустить.

Я успешно использовал эту логику, чтобы пользователи могли публиковать уже загруженное видео со своей учетной записи на моем веб-сайте на youtube. (Видео должно было быть отправлено на YouTube, и поскольку видео, как правило, являются большими файлами, я не хотел, чтобы пользователю приходилось ждать, пока видео было загружено на youtube)

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

По умолчанию сервер будет настроен таким образом, чтобы отключение не прерывало работу программы. Тем не менее, можно сделать так, чтобы пользователь отключил функцию, зарегистрированную с помощью register_shutdown_function , сбор мусора, и сценарий завершится.

Поскольку это то, что может быть настроено в нескольких разных местах, было бы проще всего запустить тест, но это директива php.ini. Если вы хотите настроить это на глобальном уровне, вы можете установить ignore_user_abort = Off в php.ini. Если вы хотите это на уровне сайта, вы можете использовать php_value ignore_user_abort off в htaccess в родительском каталоге текущего сайта. В противном случае вы можете использовать ignore_user_abort(false); ,

Конечно, на общем сервере нет гарантии, что у вас есть контроль над htaccess или php.ini, поэтому вам просто нужно использовать ignore_user_abort(false); ,