I have a simple angular app that has two views that are loaded using ngRoute. I need to do some clean up on the server when the user navigates between views and when the user leaves the page (refreshes window, closes tab, or closes browser).
我有一个简单的角度应用程序,有两个使用ngRoute加载的视图。当用户在视图之间导航以及用户离开页面时(刷新窗口,关闭选项卡或关闭浏览器),我需要在服务器上进行一些清理。
My first stop was here: Showing alert in angularjs when user leaves a page. It solved the first case where the user navigates between views. I've handled the clean up like this:
我的第一站就在这里:当用户离开页面时在angularjs中显示警报。它解决了用户在视图之间导航的第一种情况。我已经处理了这样的清理:
$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();
}
});
However, I haven't been able to handle the case where the user leaves the page. Following the above answer and this Google Groups post: https://groups.google.com/forum/#!topic/angular/-PfujIEdeCY I tried this:
但是,我无法处理用户离开页面的情况。按照上述答案和此Google网上论坛帖子: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.
};
But it did not work. Then I've read here: How to execute ajax function onbeforeunload? that the request needs to be synchronous and here: How to $http Synchronous call with AngularJS that Angular does not support this (although this one might be outdated).
但它没有用。然后我在这里阅读:如何在onbeforeunload上执行ajax函数?请求需要同步,这里:如何$ http与AngularJS同步调用Angular不支持这一点(尽管这可能已经过时)。
I've also tried calling $http directly (without the service) but that did not work either. At this point I'm stuck. Any suggestions / leads would be really appreciated.
我也试过直接调用$ http(没有服务),但这也没有用。此时我被困住了。任何建议/线索将非常感激。
Thanks in advance!
提前致谢!
2 个解决方案
#1
13
The problem is that angular always make ASYNCHRONOUS calls with the $http service (and you can’t change that behavior). Since the page exits before the $http service have a chance to emit the requests you are not getting the desired result.
问题是angular总是使用$ http服务进行ASYNCHRONOUS调用(并且您无法更改该行为)。由于页面在$ http服务有机会发出请求之前退出,因此无法获得所需的结果。
If you want a workarround without using any third party libraries try the following code:
如果您想要一个不使用任何第三方库的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);
}
It will block UI until the request is completed, so try to make the server fast or the user will notice.
它将阻止UI直到请求完成,因此尝试使服务器快速或用户会注意到。
#2
7
Solution is to call $rootScope.$digest();
after firing your $http
calls in your onbeforeunload
callback. The reason is that angular's $http
methods wrap the config in an immediately resolved promise which means the ajax request doesn't actually get fired until the next tick. Other browsers appear to allow one more tick after the onbeforeunload
tick, but not IE11 (the only version of IE in which I tested). Forcing the digest cycle avoids the need to wait until the next tick.
解决方法是调用$ rootScope。$ digest();在onbeforeunload回调中触发$ http调用之后。原因是angular的$ http方法将配置包装在一个立即解决的promise中,这意味着ajax请求实际上不会被触发直到下一个tick。其他浏览器在onbeforeunload tick之后似乎允许多一个tick,但不是IE11(我测试的IE的唯一版本)。强制摘要周期避免了等到下一个滴答的需要。
#1
13
The problem is that angular always make ASYNCHRONOUS calls with the $http service (and you can’t change that behavior). Since the page exits before the $http service have a chance to emit the requests you are not getting the desired result.
问题是angular总是使用$ http服务进行ASYNCHRONOUS调用(并且您无法更改该行为)。由于页面在$ http服务有机会发出请求之前退出,因此无法获得所需的结果。
If you want a workarround without using any third party libraries try the following code:
如果您想要一个不使用任何第三方库的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);
}
It will block UI until the request is completed, so try to make the server fast or the user will notice.
它将阻止UI直到请求完成,因此尝试使服务器快速或用户会注意到。
#2
7
Solution is to call $rootScope.$digest();
after firing your $http
calls in your onbeforeunload
callback. The reason is that angular's $http
methods wrap the config in an immediately resolved promise which means the ajax request doesn't actually get fired until the next tick. Other browsers appear to allow one more tick after the onbeforeunload
tick, but not IE11 (the only version of IE in which I tested). Forcing the digest cycle avoids the need to wait until the next tick.
解决方法是调用$ rootScope。$ digest();在onbeforeunload回调中触发$ http调用之后。原因是angular的$ http方法将配置包装在一个立即解决的promise中,这意味着ajax请求实际上不会被触发直到下一个tick。其他浏览器在onbeforeunload tick之后似乎允许多一个tick,但不是IE11(我测试的IE的唯一版本)。强制摘要周期避免了等到下一个滴答的需要。