window.onbeforeunload ajax-запрос в Chrome - PullRequest
45 голосов
/ 09 февраля 2011

У меня есть веб-страница, которая управляет удаленным управлением машиной через Ajax. Когда пользователь уходит со страницы, я хотел бы автоматически отключиться от машины. Итак, вот код:

window.onbeforeunload = function () {
  bas_disconnect_only();
}

Функция отключения просто отправляет HTTP-запрос GET сценарию на стороне сервера PHP, который выполняет фактическую работу по отключению:

function bas_disconnect_only () {
   var xhr = bas_send_request("req=10", function () {
   });
}

Это отлично работает в FireFox. Но с Chrome запрос ajax вообще не отправляется. Существует недопустимый обходной путь: добавление предупреждения в функцию обратного вызова:

function bas_disconnect_only () {
   var xhr = bas_send_request("req=10", function () {
     alert("You're been automatically disconnected.");
   });
}

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

Может кто-нибудь сказать мне, достижимо ли это с помощью Chrome? То, что я делаю, выглядит для меня совершенно законным.

Спасибо

Ответы [ 6 ]

67 голосов
/ 02 декабря 2013

Это относится к более новым версиям Chrome.

Как @Garry English сказал , отправка запроса async на странице onunload не будет работать, так как браузер прервет поток перед отправкой запроса. Отправка запроса sync должна работать, хотя.

Это было верно до версии 29 Chrome, но в Chrome V 30 он внезапно перестал работать , как указано здесь .

Похоже, что единственный способ сделать это сегодня - использовать onbeforeunload событие , как предлагается здесь .

НО ПРИМЕЧАНИЕ: другие браузеры вообще не позволяют отправлять запросы Ajax в событии onbeforeunload. так что вам нужно будет выполнить действие как в разгрузке, так и перед загрузкой, и проверить, было ли оно уже выполнено.

Примерно так:

var _wasPageCleanedUp = false;
function pageCleanup()
{
    if (!_wasPageCleanedUp)
    {
        $.ajax({
            type: 'GET',
            async: false,
            url: 'SomeUrl.com/PageCleanup?id=123',
            success: function ()
            {
                _wasPageCleanedUp = true;
            }
        });
    }
}


$(window).on('beforeunload', function ()
{
    //this will work only for Chrome
    pageCleanup();
});

$(window).on("unload", function ()
{
    //this will work for other browsers
    pageCleanup();
});
40 голосов
/ 08 июня 2012

У меня возникла та же проблема, когда Chrome не отправлял запрос AJAX на сервер в событии window.unload.

Я смог заставить его работать, только если запрос был синхронным. Я смог сделать это с помощью Jquery и установить для свойства async значение false :

$(window).unload(function () {
   $.ajax({
     type: 'GET',
     async: false,
     url: 'SomeUrl.com?id=123'
   });
});

Приведенный выше код работает для меня в IE9, Chrome 19.0.1084.52 m и Firefox 12.

18 голосов
/ 05 ноября 2015

Оформить метод Navigator.sendBeacon () , созданный для этой цели.

На странице MDN написано:

Метод navigator.sendBeacon () может использоваться для асинхронного передать небольшие HTTP-данные из User Agent на веб-сервер.

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

Это относительно новый API, который пока не поддерживается IE.

3 голосов
/ 09 февраля 2011

Попробуйте создать переменную (предпочтительно Boolean) и изменить ее после получения ответа от вызова Ajax.И поместите функцию bas_disconnect_only() в цикл while.У меня тоже когда-то была такая проблема.Я думаю, что это происходит потому, что Chrome не ждет вызова Ajax.Я не знаю, как я это исправил, и я не пробовал этот код, поэтому я не знаю, работает ли он.Вот пример этого:

var has_disconnected = false;
window.onbeforeunload = function () {
    while (!has_disconnected) {
        bas_disconnect_only();
        // This doesn't have to be here but it doesn't hurt to add it:
        return true;
    }
}

А внутри функции bas_send_request() ( xmlhttp - HTTP-запрос):

xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
        has_disconnected = true;
}

Удачи и янадеюсь, это поможет.

0 голосов
/ 19 апреля 2019

Я искал способ обнаружения выхода из страницы с помощью запроса AJAX .Это работало как каждый раз, когда я использую это, и проверяю это с MySQL.Это код (работал в Google Chrome ):

    $(window).on("beforeunload", function () {
        $.ajax({
             type: 'POST',
             url: 'Cierre_unload.php',
             success: function () {
             }
        })
    })
0 голосов
/ 12 апреля 2019

Мне приходилось отслеживать любые случаи, когда пользователь покидает страницу и отправляет ajax-запрос на бэкэнд.

var onLeavePage = function() {
    $.ajax({
        type: 'GET',
        async: false,
        data: {val1: 11, val2: 22},
        url: backend_url
    });
};

/**
 * Track user action: click url on page; close browser tab; click back/forward buttons in browser
 */
var is_mobile_or_tablet_device = some_function_to_detect();
var event_name_leave_page = (is_mobile_or_tablet_device) ? 'pagehide' : 'beforeunload';
window.addEventListener(event_name_leave_page, onLeavePage);

/**
 * Track user action when browser tab leave focus: click url on page with target="_blank"; user open new tab in browser; blur browser window etc.
 */
(/*@cc_on!@*/false) ?  // check for Internet Explorer
    document.onfocusout = onLeavePage :
    window.onblur = onLeavePage;

Имейте в виду, что событие «pagehide» запускается в настольном браузере, но не срабатывает, когда пользователь нажимает кнопки назад / вперед в браузере (тестирование в последней текущей версии Mozilla Firefox).

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