Как отправить запрос Ajax, когда сеть закрывает страницу

внешний интерфейс

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

Эта статья в основном разделена на две части, чтобы объяснить, как заполнить отчет о поведении при выходе.

1. Мониторинг событий

Браузер имеет два события, которые можно использовать для прослушивания закрытия страницы:beforeunloadа такжеunload.beforeunloadВызывается, когда документы и ресурсы собираются закрыть, документ все еще виден, а событие закрытия все еще можно отменить. Например, следующий способ написания приведет к тому, что у пользователя появится всплывающее окно, напоминающее пользователю, следует ли закрыть страницу при обновлении или закрытии страницы.

window.addEventListener("beforeunload", function (event) {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '';
});

unloadЭто происходит, когда страница уже удаляется, а документ находится в следующем состоянии: 1. Все ресурсы еще существуют (изображения, фреймы и т.д.) 2. Все ресурсы невидимы для пользователя 3. Взаимодействие с интерфейсом затруднено. неверный (window.open, alert, confirmд.); 4. Ошибка не останавливает процесс удаления документа.

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

2. Запрос на отправку

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

У нас есть несколько способов решить эту проблему:

Сценарий 1. Отправка синхронного запроса ajax

var oAjax = new XMLHttpRequest();

oAjax.open('POST', url + '/user/register', false);//false表示同步请求

oAjax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

oAjax.onreadystatechange = function() {
    if (oAjax.readyState == 4 && oAjax.status == 200) {
        var data = JSON.parse(oAjax.responseText);
    } else {
        console.log(oAjax);
    }
};

oAjax.send('a=1&b=2');

Хотя этот метод эффективен, пользователю необходимождатьСтраница может быть закрыта только после выполнения запроса. Плохой пользовательский опыт.

Вариант 2: отправить асинхронный запрос и игнорировать прерывание ajax на стороне сервера.

Хотя асинхронный запрос будет прерван браузером, если сервер может игнорировать прерывание, он все равно может быть выполнен нормально. Например, PHP имеетignore_user_abortФункции могут игнорировать прерывание. Для этого необходимо изменить фон, что, как правило, невозможно.

Сценарий 3: Использованиеnavigator.sendBeaconотправить асинхронный запрос

согласно сMDNВступление к:

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

Как видно из введения, этот метод используется для отправки запроса при выходе пользователя. Идеально подходит для этого сценария. Он используется следующим образом:

navigator.sendBeacon(url [, data]);

Данные, отправляемые sendBeacon, могут бытьArrayBufferView, Blob, DOMString, илиFormDataтип данных.

Ниже приведены несколько способов использования sendBeacon для отправки запросов.Формат заголовка и содержимого можно изменить, поскольку способ связи с сервером обычно фиксирован.Если заголовок или содержимое изменены, сервер не может их нормально распознать.

(1) Используйте Blob для отправки Преимущество использования большого двоичного объекта для отправки заключается в том, что вы можете самостоятельно определить формат и заголовок содержимого. Например, в следующем методе настройки вы можете установить тип содержимого как application/x-www-form-urlencoded.

blob = new Blob([`room_id=123`], {type : 'application/x-www-form-urlencoded'});
navigator.sendBeacon("/cgi-bin/leave_room", blob);

image-20190211094506994

(2) Используйте объект FormData, но тогда для типа содержимого будет установлено значение «multipart/form-data».

var fd = new FormData();
fd.append('room_id', 123);
navigator.sendBeacon("/cgi-bin/leave_room", fd);

image-20190211094625904

(3) данные также могут быть использованыURLSearchParamsобъект, тип содержимого будет установлен на "text/plain;charset=UTF-8".

var params = new URLSearchParams({ room_id: 123 })
navigator.sendBeacon("/cgi-bin/leave_room", params);

image-20190211095036518

Попробовав, вы можете обнаружить, что для отправки удобнее использовать blob, а настройка содержимого более гибкая.Если отправленное сообщение перехвачено и обнаружено, что фон не распознан, вы можете попробовать изменить строку или заголовок содержание, чтобы найти подходящий способ отправки запроса.

Ссылка на ссылку:

  1. sendBeacon API not working temporarily due to security issue, any workaround?

  2. Sending AJAX Data when User Moves Away / Exits from Page

  3. Setting HTTP Headers in a Beacon Request


Технологический еженедельник IVWEBШок в сети, обратите внимание на публичный номер: сообщество IVWEB, регулярно каждую неделю публикуйте качественные статьи.

  • Сборник статей еженедельника:weekly
  • Командные проекты с открытым исходным кодом:Feflow