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

Как я могу обработать событие закрытия вкладки браузера в Angular? Только закрыть, а не обновить

Моя цель - удалить файлы cookie пользователей, когда закрыта вкладка браузера.

Возможно ли это? Можно ли обработать событие закрытия вкладки браузера без обновления?

Если я использую события beforeunload или unload, функция запускается при обновлении страницы пользователя, я не хочу этого, я хочу просто запустить при закрытой вкладке.

Как это сделать в Angular?

4b9b3361

Ответ 1

Это трагически, а не простая проблема для решения. Но это может быть сделано. Ответ ниже объединен из многих различных ответов SO.

Простая часть: Известно, что окно разрушается. Вы можете использовать дескриптор события onunload, чтобы обнаружить это.

Tricky Part:

Обнаружение, если это обновление, ссылка или событие закрытия окна. Удаление ссылки следует и форма представления достаточно проста:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Бедственное решение

Проверка event.clientY или event.clientX, чтобы определить, что было нажато, чтобы запустить событие.

function doUnload(){
 if (window.event.clientX < 0 && window.event.clientY < 0){
   alert("Window closed");
 }
 else{
   alert("Window refreshed");
 }
}

Y-Axis не работает, потому что это отрицательно для кликов на кнопках перезагрузки или закрытия вкладки/окна, и положительно, когда сочетания клавиш используются для перезагрузки (например, F5, Ctrl-R,...) и закрытия окна (например, Alt-F4). X-Axis не полезен, поскольку разные браузеры имеют разные расположения кнопок. Однако, если вы ограничены, то выполнение кодов событий через ряд if-elses может быть вашим лучшим выбором. Помните, что это, безусловно, не является надежным.

Принятое решение

(взято из Julien Kronegg) Использование локального хранилища HTML5 и клиентской/серверной AJAX-связи. Предостережение. Этот подход ограничен браузерами, поддерживающими локальное хранилище HTML5.

На вашей странице добавьте onunload к окну следующему обработчику

function myUnload(event) {
    if (window.localStorage) {
        // flag the page as being unloading
        window.localStorage['myUnloadEventFlag']=new Date().getTime();
    }

    // notify the server that we want to disconnect the user in a few seconds (I used 5 seconds)
    askServerToDisconnectUserInAFewSeconds(); // synchronous AJAX call
}

Затем добавьте тело onloadon к следующему обработчику

function myLoad(event) {
    if (window.localStorage) {
        var t0 = Number(window.localStorage['myUnloadEventFlag']);
        if (isNaN(t0)) t0=0;
        var t1=new Date().getTime();
        var duration=t1-t0;
        if (duration<10*1000) {
            // less than 10 seconds since the previous Unload event => it a browser reload (so cancel the disconnection request)
            askServerToCancelDisconnectionRequest(); // asynchronous AJAX call
        } else {
            // last unload event was for a tab/window close => do whatever
        }
    }
} 

На сервере собирайте запросы на разъединение в списке и задайте таймер, который регулярно проверяет список (я использовал каждые 20 секунд). Как только тайм-аут запроса на разъединение (т.е. 5 секунды ушли), отключите пользователя от сервера. Если то отмена запроса на разъединение соответствующий запрос разъединения удаляется из списка, так что пользователь не будет отключен.

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

Закрытие комментариев (каламбур):

Поскольку вы хотите удалить куки, когда окно закрыто, я предполагаю, что он не будет использоваться в будущем сеансе. Если это правильное предположение, описанный выше подход будет работать хорошо. Вы сохраняете недействительный файл cookie на сервере (когда клиент отключен), когда клиент создает новый сеанс, JS по умолчанию отправляет куки файл, после чего вы знаете его с более старого сеанса, удалите его и, новый, который будет установлен на клиенте.

Ответ 2

$window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  console.log("closing the tab so do your small interval actions here like cookie removal etc but you cannot stop customer from closing");
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

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

javascript обнаружить браузер закрыть вкладку/закрыть браузер

Update: Я изучал этот вопрос вместе с некоторыми рекомендациями. И помимо этого выше, лучший способ справиться с такими случаями - создание сеансов без тайм-аута активности может составлять 25-30 минут. Преобразуйте все файлы cookie, которые необходимо уничтожить в сеансах с таймаутом. Кроме того, вы можете установить срок действия cookie, но затем файл cookie останется в браузере до следующего входа. Менее 25-30 минут бездействия сессии не являются полностью надежными, так как вы можете выйти из системы, если клиент не использует браузер в течение 10-15 минут. Я даже пробовал события захвата из событий (< a > ) или (< submit > ) или (keypress). Проблема в том, что он хорошо справляется с обновлением страницы. Но это не устраняет проблему закрытия клиента браузером или вкладкой браузера, прежде чем ваши файлы cookie будут удалены. Это то, что вы должны учитывать в своем прецеденте и активно торговать из-за отсутствия контроля над ним. Лучше изменить дизайн на его зависимость от лучшей архитектуры, чем столкнуться с упомянутыми проблемами позже.

Ответ 4

Если ваша цель - удалить куки, когда браузер закрыт, не устанавливайте срок действия. Cookies без истечения срока действия удаляются при закрытии браузера.

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

Нижняя линия:

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

Ответ 5

Я знаю, что прошло некоторое время с тех пор, как был задан этот вопрос, но я думал, что внес свой ответ. Лучший способ, по которому я нашел перезагрузку страницы без потери файлов cookie, и удалить файлы cookie в окне или вкладке закрыть было использовать ng-keydown для просмотра F5 Keypress (KeyCode 116).

HTML

<body ng-controller="exitController" ng-keydown="isRefresh($event)">

CONTROLLER

yourApp.controller('exitController', ['$rootScope', '$scope', '$window', '$cookies', function($rootScope, $scope, $window, $cookies) {
//set refresh to false to start out, it will become true only when we hit the refresh page
$scope.refresh = false;

//This is where we'll actually clear our cookies in the event of a window close
$scope.clearCookies = function() {
    $cookies.remove('sessionData');
    $cookies.remove('ss-id');
    $cookies.remove('ss-pid');
};

//When the user types any key, it will be assessed.
$scope.isRefresh = function(e) {
    var keyCode = e.keyCode; //find the key that was just pressed
    if(keyCode === 116) { //if the key that was pressed is F5, then we know it was a refresh
        $scope.refresh = true;
    }
}

//event that handles all refresh requests
window.onbeforeunload = function (e) {
    if (!$scope.refresh) { //as long as the trigger for the refresh wasnt initiated by F5, we remove the cookies
        $scope.clearCookies();
    }
};

}]);