Может ли событие unload использоваться для надежного запуска запроса ajax? - PullRequest
36 голосов
/ 27 августа 2010

Мне нужен метод для мониторинга пользовательских сеансов редактирования, и одно из рассматриваемых мной решений будет использовать событие unload для отправки ajax-запроса, чтобы сообщить серверу об окончании сеанса редактирования. (См .: Мониторинг сеансов пользователей для предотвращения конфликта редактирования )

Мои (довольно ограниченные) показания по событию unload указывают на то, что коды, прикрепленные к этому обработчику, должны выполняться быстро и поэтому обычно используются для очистки объектов для предотвращения утечек памяти.

У меня вопрос, может ли это работать достаточно надежно для этой цели?

PS. Я знаю о опции async: false.

Ответы [ 5 ]

36 голосов
/ 29 августа 2010

Этот метод достаточно надежен, если ваш сервер достаточно быстр для ответа. Что-то, чтобы действительно остерегаться, хотя. Если вы закроете браузер и отправите AJAX-запрос о событии unload, очень велика вероятность того, что ответ не будет возвращен с сервера вовремя, пока объект окна не будет уничтожен. Что происходит в этом случае (по крайней мере, с IE), так это то, что он потеряет связь с вашим объектом соединения и не завершит его корректно, пока не истечет время ожидания соединения. Если на вашем сервере не включена поддержка активности соединения, после закрытия 2 окон (хотя еще одно окно остается открытым) у вас закончатся открытые соединения с сервером (для IE6-7, для IE8 - 6 окон) и вы не сможете открыть свой веб-сайт, пока не истечет время ожидания подключения.

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

Похоже, что если вы закроете самое последнее окно браузера, IE должным образом разрушит соединение, но если откроется еще одно окно, оно не будет.

P.S. И просто чтобы прокомментировать ответ выше, AJAX на самом деле не асинхронный. По крайней мере, реализация JS этого не делает. После отправки запроса ваш код JS все еще будет ожидать ответа от сервера. Он не будет блокировать выполнение вашего кода, но поскольку для ответа серверу может потребоваться некоторое время (или достаточно долго, чтобы Windows прекратила работу с оконным объектом IE), вы можете и, вероятно, столкнетесь с проблемой, описанной выше.

12 голосов
/ 25 декабря 2010

Вы пытались использовать

var i = new Image(1,1); 
i.src='http://...'

И просто возвращать пустое изображение с сервера.Я думаю, что это должно быть надежным, сценарий будет блокировать.Кстати: приятно добавить метку времени для предотвращения кеширования.

3 голосов
/ 27 августа 2010

У нас есть случай, когда нам это нужно.Это страница отчета, которая требует серьезной памяти на сервере, поэтому мы хотели освободить ее сразу же, как только они покинули страницу.Мы создали набор фреймов и добавили туда обработчик выгрузки.Самым надежным способом было установить src изображения для скрипта освобождения.Мы фактически использовали как unload, так и onbeforeunload для кросс-браузерной совместимости.В ночных веб-китах это не сработало, но с этим все было в порядке.

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

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

Это не решает проблему оставления страницы надолгоДля этого вам необходим некоторый мониторинг активности пользователей и покиньте эту страницу после периода бездействия (обязательно подтвердите это у пользователя)

1 голос
/ 27 августа 2010

Вам нужно будет провести собственное тестирование на предмет того, работает ли ваш конкретный сценарий со временем, которое у вас есть в unload, но выполнение запроса AJAX выполняется довольно быстро, поскольку AJAX является асинхронным.Вы просто отправляете запрос и все готово!(Возможно, вам придется очистить объект запроса, который вы только что создали.)

Если вы хотите убедиться, что запрос AJAX сделал это, вам придется больше беспокоиться / используйте async:falseвариант (как это обсуждение указывает).Но просто отправка - это быстрая операция «бум и все готово».

0 голосов
/ 02 июля 2014

У меня был случай, когда мне нужно было только уведомить серверную сторону о разгрузке, и мне было все равно, какой ответ.

Если это ваш случай, вы можете ignore_user_abort и тогда вы знаете, что это произойдет "надежно"

...