2014-02-10 4 views
8

У меня есть простое угловое приложение, которое имеет два вида, которые загружаются с помощью ngRoute. Мне нужно сделать очистку на сервере, когда пользователь перемещается между представлениями и когда пользователь покидает страницу (обновляет окно, закрывает вкладку или закрывает браузер).Как отправить HTTP-запрос onbeforeunload в AngularJS?

Моя первая остановка была здесь: Showing alert in angularjs when user leaves a page. Он решил первый случай, когда пользователь перемещается между представлениями. Я обрабатывается моются так:

$scope.$on('$locationChangeStart', function (event) { 
    var answer = confirm("Are you sure you want to leave this page?") 
    if (answer) { 
     api.unlock($scope.id); //api is a service that I wrote. It uses angular $http service to handle communications and works in all other cases. 
    } else { 
     event.preventDefault(); 
    } 
}); 

Однако, я не был в состоянии обрабатывать случай, когда пользователь покидает страницу. После ответа выше и этого Google Groups пост: https://groups.google.com/forum/#!topic/angular/-PfujIEdeCY Я попытался это:

window.onbeforeunload = function (event) { 
    api.unlock($scope.id); //I don't necessarily need a confirmation dialogue, although that would be helpful. 
}; 

Но это не сработало. Затем я прочитал здесь: How to execute ajax function onbeforeunload?, что запрос должен быть синхронным, а здесь: How to $http Synchronous call with AngularJS, что Angular не поддерживает это (хотя это может быть устаревшим).

Я также попытался позвонить в $ http напрямую (без обслуживания), но это тоже не сработало. В этот момент я застрял. Любые предложения/выводы будут действительно оценены.

Заранее благодарен!

+0

Вы можете показать информацию о том, что данные будут потеряны, если пользователь теперь переместится, просто верните строку внутри обработчика onbeforeunload. – Sebastian

ответ

13

Проблема заключается в том, что угловые всегда делают вызовы ASYNCHRONOUS с помощью службы $ http (и вы не можете изменить это поведение). Поскольку страница завершается до того, как служба $ http имеет шанс исправить запросы, вы не получите желаемый результат.

Если вы хотите workarround без использования каких-либо сторонние библиотеки попробуйте следующий код:

var onBeforeUnload = function() { 

    var data = angular.toJson($scope.id...);//make sure you $scope is legal here... 
    var xmlhttp = new XMLHttpRequest(); 
    xmlhttp.open("POST", "apiURL/unlock", false);//the false is for making the call synchronous 
    xmlhttp.setRequestHeader("Content-type", "application/json"); 
    xmlhttp.setRequestHeader("Authorization", token); 
    xmlhttp.send(data); 
} 

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

+0

Это по-прежнему зависит от типа вызова сервера. Я пытаюсь использовать аналогичную вещь, когда я вызываю сервер, чтобы убить объект сеанса. Но столкнулся с проблемой, когда пользователь просто перезагружает текущую страницу :(поэтому сеанс по-прежнему должен быть активным. –

7

Решение должно называть $rootScope.$digest(); после обстрела $http вызовов в вашем обратном вызове onbeforeunload. Причина в том, что угловые методы $http обертывают конфигурацию в немедленно разрешенное обещание, что означает, что запрос ajax фактически не срабатывает до следующего тика. Другие браузеры, похоже, позволяют еще один тик после отметки onbeforeunload, но не IE11 (единственная версия IE, в которой я тестировал). Принуждение цикла дайджеста позволяет избежать необходимости ждать следующего тика.

+0

Это работало на Chrome (версия 51.0.2704.103 (64-разрядная версия)) –

+0

Спасибо! Это сработало для IE11 для меня. – lwalden

Смежные вопросы