好的,所以可以使用異步XHR和2個事件完成:beforeunload和unload。
我試圖在一個事件中完成它,但直到循環結束時纔會發送請求,即使請求是在循環之前發送的。
在beforeunload處理程序中,發送異步請求並保存當前時間。然後在卸載處理程序中,如果沒有足夠的時間或服務器響應(檢查readyState),則會放置一個while循環。 當循環結束時,瀏覽器可以自由卸載窗口。
這是代碼。如果瀏覽器支持,我也啓用發送信標。
var unloadRequest = null,
requestStartTime = null,
isBeaconSupported = (navigator && typeof navigator.sendBeacon === 'function');
window.onbeforeunload = function() {
if (isBeaconSupported) {
unloadRequest = new XMLHttpRequest();
unloadRequest.withCredentials = true;
unloadRequest.open('POST', '/beacon', true);
unloadRequest.setRequestHeader("Content-Type", "text/plain");
requestStartTime = performance.now();
unloadRequest.send(JSON.stringify({ test: true, _sentBy: 'XMLHttpRequest' }));
}
//return true;
};
window.onunload = function() {
if (isBeaconSupported) {
navigator.sendBeacon('/beacon', JSON.stringify({ test: true, _sentBy: 'beacon' }))
} else if (unloadRequest) {
//continue the loop if time is left and the request havent finished
while (requestStartTime + 3000 > performance.now() && unloadRequest.readyState !== XMLHttpRequest.DONE) {
//console.log(unloadRequest.readyState);
}
console.log('request finished or timed out')
console.log('it took: ' + (performance.now() - requestStartTime) + 'ms');
}
};