Не ожидает ответа от AJAX-запроса - PullRequest
9 голосов
/ 21 июля 2011

Предположим, я делаю 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? Казнь все еще продолжается? Это остановилось? Я имею в виду, что у него не было возможности ответить, так что ...

Ответы [ 4 ]

8 голосов
/ 27 августа 2011

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

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

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

<?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- но в любом случае это должно отличаться от времени ожидания веб-сервера.

6 голосов
/ 21 июля 2011

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

ignore_user_abort(true);

это не должно прерывать обработку вашего кода

0 голосов
/ 27 августа 2011

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

По умолчанию сервер будет настроен таким образом, чтобы отключение не прерывало работу программы. Однако можно сделать так, чтобы при отключении пользователя была активирована функция, зарегистрированная с 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);.

0 голосов
/ 27 августа 2011

Возможно, вы захотите проверить ответы на Этот вопрос . В основном, когда вы делаете свой 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 &"');

И, наконец, в файле реалий-сценариев. Просто включите фактический код, который вы хотите запустить.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...