Javascript / angular:从onunload

时间:2016-12-08 14:28:42

标签: javascript angularjs onunload

我正在使用一个锁定服务器资源的Web应用程序。要解锁它们,它必须使用HTTP DELETE删除服务器上的资源。我知道这不可靠,并且定期清理也可以解锁它们,但目标是尽快解锁资源。

我无法改变锁定架构(它不是我的系统),我只需要在解锁时做出最好的准备。

我需要解锁的一点是选项卡或浏览器关闭时。首先,我处理onbeforeunload,如果文档是脏的,则提示用户确认他们要关闭:

$window.onbeforeunload = function() {
    if (documentIsDirty) {
        return "Some prompt text";
    }
};

我无法在onbeforeunload中解锁,因为用户可能会选择取消关闭。但是在onbeforeunload和onunload之间没有事件(如果我错了,请纠正我)。

如果我尝试在onunload中进行调用,那么一旦onunload函数返回,tab / session就会被破坏。麻烦的是,在http请求完成之前,事实证明该资源实际上并未解锁。

$window.onunload = function() {
    $http.delete('/a/lock/url');

    // I've tried forcing a digest cycle to try and flush the request
    // through, but it never gets sent either way
    $rootScope.$digest();
};

现在,我知道在Javascript中实际上阻止是一种诅咒,但似乎一旦onload返回,那就是她所写的全部内容。

在http请求实际完成之前是否有任何方法可以阻止,并阻止onunload在此之前返回?

[UPDATE] 解决方案如下 - 同步使用XMLHttpRequest。它被大声贬低,但(在撰写本文时)至少仍然在Chrome中使用。

var request = new XMLHttpRequest();
request.open('DELETE', url, false);
request.setRequestHeader('X-XSRF-TOKEN', myXSRFToken);
request.send();

2 个答案:

答案 0 :(得分:1)

$ http将始终异步执行请求,因为在内部它只使用XMLHttpRequest并始终将true作为第三个参数传递给请求的open函数。来自XMLHttpRequest's open function的MDN文档:

  

可选的布尔参数,默认为true,指示是否异步执行操作。如果此值为false,则send()方法在收到响应之前不会返回。

如果您想要执行同步请求,可以直接使用XMLHttpRequest并将false作为第三个参数传递给open。由于这是在网站关闭时,无论如何都不必使用Angular的$ http。

答案 1 :(得分:0)

最近,在进行此类活动时遇到了相同的问题,并使用navigator.sendBeacon()解决了该问题。navigator.sendBeacon()方法通过HTTP异步将少量数据发送到Web服务器。对于最新的浏览器,您可以喜欢

window.addEventListener('beforeunload', function (event) {
    data = new FormData();
    // for CSRF Token
    token = $('meta[name="csrf-token"]').attr('content');
    data.append("key", value);
    data.append("authenticity_token", token);
  
    navigator.sendBeacon("URL", data);
    
    // Cancel the event as stated by the standard.
    event.preventDefault();
    // Chrome requires returnValue to be set.
    event.returnValue = 'Are you sure you want to leave this page without saving?';
  });

有关更多详细信息,请检出Navigator.sendBeacon()Window: beforeunload event