2014-02-10 90 views
8

我有一個簡單的角度應用程序,它有兩個使用ngRoute加載的視圖。當用戶在視圖之間導航並且用戶離開頁面時(刷新窗口,關閉選項卡或關閉瀏覽器),我需要在服務器上進行一些清理。如何發送在AngularJS中未被加載的HTTP請求?

我的第一站是這裏: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(); 
    } 
}); 

但是,我一直無法處理用戶離開頁面的情況。按照上面的答案,這個谷歌網上論壇帖子: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

問題是角度始終使用$ 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

解決方法是在您的onbeforeunload回調中觸發您的$http呼叫後致電$rootScope.$digest();。原因在於angular的$http方法將配置封裝在一個立即解決的承諾中,這意味着ajax請求在下一個tick之前不會被觸發。其他瀏覽器似乎允許在onbeforeunload打勾後再打勾,但不打IE11(我測試過的IE的唯一版本)。強制摘要循環可以避免等待下一次打勾。

+0

這適用於Chrome(版本51.0.2704.103(64位)) –

+0

謝謝!此工作適用於IE11爲了我。 – lwalden