Останавливается ли выполнение php после того, как пользователь покидает страницу?

Я хочу запустить относительно трудоемкий скрипт на основе некоторого ввода формы, но я бы предпочел не прибегать к cron, поэтому мне интересно, будет ли страница php, запрошенная через ajax, продолжать выполняться до завершения или она остановится, если пользователь покидает страницу.

На самом деле он не выводится в браузер до json_encode в конце файла, так что все, что было до этого, все еще выполнялось?


person Stephen Belanger    schedule 14.08.2009    source источник


Ответы (5)


По-разному.

Из http://us3.php.net/manual/en/features.connection-handling.php:

Когда PHP-скрипт работает нормально, состояние NORMAL активно. Если удаленный клиент отключается, устанавливается флаг состояния ABORTED. Отключение удаленного клиента обычно происходит из-за того, что пользователь нажимает кнопку STOP.

Вы можете решить, хотите ли вы, чтобы отключение клиента вызывало прерывание вашего сценария. Иногда бывает удобно, чтобы ваши сценарии всегда выполнялись до конца, даже если нет удаленного браузера, получающего выходные данные. Однако по умолчанию сценарий прерывается при отключении удаленного клиента. Это поведение можно настроить с помощью директивы ignore_user_abort php.ini, а также соответствующей директивы php_value ignore_user_abort Apache httpd.conf или с помощью функции ignore_user_abort().

Казалось бы, ответ на ваш вопрос: «Да, скрипт завершится, если пользователь покинет страницу».

Однако помните, что в зависимости от используемого внутреннего SAPI (например, mod_php) php не может определить, что клиент прервал соединение, пока не будет предпринята попытка отправить информацию клиенту. Если ваш продолжительный сценарий не выдает flush(), сценарий может продолжать работать, даже если пользователь закрыл соединение.

Ситуация усложняется, даже если вы делаете периодические вызовы flush(), имея включение буферизации вывода вызовет перехват этих вызовов и не отправит их клиенту, пока скрипт не завершится!

Дополнительно усложняет ситуацию то, что если вы установили обработчики Apache, которые буферизуют ответ (например, mod_gzip), то снова php не обнаружит, что соединение закрыто, и скрипт продолжит работу.

Фу.

person Crescent Fresh    schedule 14.08.2009

Это зависит от ваших настроек — обычно это останавливается, но вы можете использовать ignore_user_abort(), чтобы продолжить.

person Greg    schedule 14.08.2009
comment
На php.net/manual/en/ есть большое предупреждение. function.ignore-user-abort.php, что ignore_user_abort() не гарантируется работа, если данные не могут быть отправлены клиенту, что может произойти в ряде сценариев. Смотрите мой ответ. - person Crescent Fresh; 15.08.2009

В зависимости от конфигурации веб-сервера и/или PHP процесс PHP может или не может уничтожить поток, когда пользователь завершает HTTP-соединение. Если запрос AJAX находится в состоянии ожидания, когда пользователь уходит со страницы, это зависит от браузера, убивающего запрос (не гарантируется) поверх конфигурации вашего сервера (не гарантируется). Не тот ответ, который вы хотите услышать!

Я бы порекомендовал создать рабочую очередь в плоском файле или базе данных, в которой постоянно работает демон PHP может опрашивать вакансии. Он не страдает от задержки cron, но сохраняет использование ЦП/памяти на приемлемом уровне. После завершения задания поместите результаты в плоский файл/базу данных для выборки AJAX. Или пообещайте отправить электронное письмо пользователю, как только работа будет завершена (мой предпочтительный метод).

надеюсь, это поможет

person Al.    schedule 14.08.2009

Если клиент/пользователь/загрузчик/программа просмотра прервется или отключится, сценарий продолжит работу до тех пор, пока что-то не попытается выполнить сброс новых данных для клиента. Если вы не использовали ignore_user_abort(), скрипт там умрет. В том же порядке PHP не может определить, существует ли еще клиент, не пытаясь сбросить какие-либо данные в файл httpd.

person Havenard    schedule 15.08.2009

нашел фактическое решение для моего случая, когда соединение не разрывается. СЕССИЯ на моем сервере Apache/Php должна была закрыться, прежде чем мог начаться следующий.

Браузер ожидает завершения вызова ajax после прерывания.

person Artistan    schedule 22.06.2010