Подтвердить что ты не робот

JavaScript, браузеры, закрыть окно - отправить запрос AJAX или запустить script при закрытии окна

Я пытаюсь выяснить, когда пользователь покинул указанную страницу. Нет никаких проблем с поиском, когда он использовал ссылку внутри страницы, чтобы перейти от нее, но мне как-то нужно пометить что-то вроде, когда он закрыл окно или набрал другой URL-адрес и нажал кнопку ввода. Второй не так важен, но первый. Итак, вот вопрос:

Как я могу увидеть, когда пользователь закрыл мою страницу (событие capture window.close), а затем... на самом деле не имеет значения (мне нужно отправить запрос AJAX, но если я могу заставить его запустить предупреждение, Я могу сделать все остальное).

4b9b3361

Ответ 1

Есть события unload и beforeunload javascript, но они не являются надежными для запроса Ajax (не гарантируется, что запрос, инициированный в одном из этих событий, достигнет сервера).

Поэтому делать это настоятельно рекомендуется не, и вы должны искать альтернативу.

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


Другим решением было бы использовать unload или beforeunload для выполнения запроса Sjax (синхронный JavaScript и XML), но это совершенно не рекомендуется. Выполнение этого в основном заморозит браузер пользователя до тех пор, пока запрос не будет завершен, что им не понравится (даже если запрос занимает мало времени).

Ответ 2

1) Если вы ищете способ работы во всех браузерах, то самый безопасный способ - отправить синхронный AJAX на сервер. Это не очень хороший метод, но, по крайней мере, убедитесь, что вы не отправляете слишком много данных на сервер, и сервер работает быстро.

2) Вы также можете использовать асинхронный AJAX-запрос и использовать функцию ignore_user_abort на сервере (если вы используете PHP). Однако ignore_user_abort во многом зависит от конфигурации сервера. Убедитесь, что вы проверяете это хорошо.

3) Для современных браузеров не следует отправлять запрос AJAX. Вам следует использовать новый метод navigator.sendBeacon для асинхронной отправки данных на сервер без блокировки загрузки следующей страницы. Поскольку вы хотите отправить данные на сервер до того, как пользователь уйдет со страницы, вы можете использовать этот метод в обработчике события unload.

$(window).on('unload', function() {
    var fd = new FormData();
    fd.append('ajax_data', 22);
    navigator.sendBeacon('ajax.php', fd);
});

Там также, кажется, есть polyfill для sendBeacon. Он прибегает к отправке синхронного AJAX, если метод изначально не доступен.

ВАЖНО ДЛЯ МОБИЛЬНЫХ УСТРОЙСТВ: обратите внимание, что обработчик события unload не гарантированно будет запущен для мобильных телефонов. Но событие visibilitychange гарантированно будет запущено. Так что для мобильных устройств ваш код сбора данных может потребовать небольшой доработки.

Вы можете обратиться к моей статье в блоге для реализации кода всех трех способов.

Ответ 3

Основываясь на другом ответе.

Чтобы прояснить ситуацию, в 2018 году API-интерфейс Beacon является решением этой проблемы (практически в каждом браузере)

Запросы маяка гарантированно инициируются до того, как страница выгружена, и они выполняются до конца, не требуя запроса на блокировку.

Вы можете использовать его внутри события onunload и быть уверенным, что оно будет отправлено.

$(window).on('unload', function() {

    var URL = "https://example.com/foo";
    var data = "bar";

    navigator.sendBeacon(URL, data);

});

Отличное сообщение в блоге: http://usefulangle.com/post/62/javascript-send-data-to-server-on-page-exit-reload-redirect

API маяка: https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API/Using_the_Beacon_API

Ответ 4

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

Чтобы сделать запрос доступным для сервера, мы попытались сделать код ниже: -

onbeforeunload = function() {

    //Your code goes here.

    return "";
} 

Мы используем браузер IE, а теперь, когда пользователь закрывает браузер, он получает диалог подтверждения из-за return ""; и ждет подтверждения пользователя, и это время ожидания заставляет запрос добраться до сервера.

Ответ 5

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

Обычно браузер закрывается до выполнения xhr.send(). Chrome и edge выглядят так, что они ждут, когда цикл событий javascript будет опущен до закрытия окна. Они также запускают запрос xhr в другом потоке, чем цикл событий javascript. Это означает, что если вы можете держать цикл событий достаточно длинным, xhr успешно сработает. Например, я протестировал отправку запроса xhr, а затем счет до 100 000 000. Это работало очень последовательно как для хрома, так и для меня. Если вы используете angularjs, перенос вашего вызова на $http in $apply завершает то же самое.

IE, похоже, немного отличается. Я не думаю, что IE ждет, пока цикл цикла не будет опущен, или даже для текущего стека стека. Хотя иногда он будет правильно отправлять запрос, то, что кажется гораздо чаще (80% -90% времени), заключается в том, что IE закроет окно или вкладку до того, как запрос xhr будет полностью выполнен, что приведет лишь к частичному сообщению послан. В основном сервер получает почтовый запрос, но нет тела.

Для потомков здесь код, который я использовал, был прикреплен как функция window.onbeforeunload для прослушивания:

  var xhr = new XMLHttpRequest();
  xhr.open("POST", <your url here>);
  xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  var payload = {id: "123456789"};
  xhr.send(JSON.stringify(payload));

  for(var i = 0; i < 100000000; i++) {}

Я тестировал:

Chrome 61.0.3163.100

IE 11.608.15063.0CO

Край 40.15063.0.0

Ответ 6

  Попробуй это. Я решил эту проблему в javascript, отправив ajax-вызов на сервер при просмотре или закрытии вкладки. У меня была проблема с обновлением страницы, потому что на функции onbeforeunload, включая обновление страницы. performance.navigation.type == 1 должен изолировать обновление от закрытия (в браузере mozzila).

$(window).bind('mouseover', (function () { // detecting DOM elements
    window.onbeforeunload = null;
}));

$(window).bind('mouseout', (function () { //Detecting event out of DOM
      window.onbeforeunload = ConfirmLeave;
}));

function ConfirmLeave() {
   if (performance.navigation.type == 1) { //detecting refresh page(doesnt work on every browser)
   }
   else {
       logOutUser();
   }
}

$(document).bind('keydown', function (e) { //detecting alt+F4 closing
    if (e.altKey && e.keyCode == 115) {
        logOutUser();
    }    
});
function logOutUser() {
   $.ajax({
     type: "POST",
     url: GWA("LogIn/ForcedClosing"), //example controller/method
     async: false
   });
}

Ответ 7

Спустя годы после публикации вопроса я улучшил реализацию, включая nodejs и socket.io(https://socket.io) (в этом случае вы можете использовать любой вид сокетов, но это был мой личный выбор).

По сути, я открываю соединение с клиентом, а когда он зависает, я просто сохраняю данные/делаю все, что мне нужно. Очевидно, что это нельзя использовать для показа чего-либо/перенаправления клиента (так как вы делаете это на стороне сервера), но это то, что мне действительно было нужно тогда.

 io.on('connection', function(socket){
      socket.on('disconnect', function(){
          // Do stuff here
      });
 });

Итак... в настоящее время я думаю, что это будет лучше (хотя сложнее реализовать, потому что вам нужен узел, сокет и т.д., но это не так сложно; должно занять около 30 минут или около того, если вы делаете это впервые) подход, чем версия выгрузки.

Ответ 8

Я согласен с идеей Феликса, и я решил проблему с этим решением, и теперь я хочу очистить решение Server Side:

1. передать запрос с клиентской стороны серверу

2.save время последнего запроса, полученного в переменной

3. Проверьте время сервера и сравните его с переменной последней полученной   Запрос

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

Ответ 9

Использование:

<body onUnload="javascript:">

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