如何在web頁面關閉或刷新以前,發送Ajax到服務端

最近在作實時視頻這塊的封裝,須要客戶端Ajax實時上報狀態給服務端,以確認用戶的當前的通話狀態。這個時候,涉及到當用戶離開客戶端時候(關閉瀏覽器),發送離線狀態給服務器。web

1、監聽瀏覽器關閉事件

瀏覽器關閉事件會有兩個,unload 和 **beforunload,二者是有區別的,從字面上來看,beforunload的調用是在 unload以前。瀏覽器

一、beforeunload在用戶即將離開頁面時觸發,它返回一個字符串,瀏覽器會向用戶展現並詢問這個字符串以肯定是否離開。bash

二、unload在用戶已經離開時觸發,咱們在這個階段僅能夠作一些沒有延遲的操做,因爲種種限制,不多被使用。服務器

三、須要注意的是,若是在兩個事件監聽中添加 alert、confirm、prompt會忽略app

四、生效狀況:異步

  • 1·關閉瀏覽器窗口
  • 2·經過地址欄或收藏夾前往其餘頁面的時候
  • 3·點擊返回,前進,刷新,主頁其中一個的時候
  • 4·點擊 一個前往其餘頁面的url鏈接的時候
  • 5·調用如下任意一個事件的時候:click,document.write()方法(輸出內容),document.open() 打開一個新的空白文檔,document.close()方法可關閉一個由open()方法打開的輸出流,並顯示選定的數據。 ,window close (),form.submit.
  • 6·當用window open打開一個頁面,並把本頁的window的名字傳給要打開的頁面的時候。
  • 7·從新賦予location.href的值的時候。
  • 8·經過input type=」submit」按鈕提交一個具備指定action的表單的時候。
  • 9.能夠用在如下元素:body, frameset, window

==上代碼==

window.onunload = function(){
	// 相關代碼
}
window.onbeforeunload = function(){
    // 相關代碼
}
window.addEventListener('unload', ()=>{
    // 相關代碼
});
window.addEventListener('beforeunload', ()=>{
    // 相關代碼
});
複製代碼

有時候兩個監聽須要配合使用,固然,避免重複調用,要作一些處理。post

2、發送請求

有了上面兩個監聽爲前提下,咱們來關心一下怎麼能把請求發送成功給服務端。若是隻是在監聽中隨便寫個請求,說不定請求還沒發出去,已經被瀏覽器中止了,異步的Ajax不必定能準確的到達服務端。下面有三個想法能夠進行實現。ui

一、請求設置爲同步(不建議)

你們第一反應多是,把請求設置爲同步請求,上代碼:url

var xml = new XMLHttpRequest();

xml.open('POST', url , false); // false表示不是異步請求

xml.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

xml.onreadystatechange = function() {
    if (xml.readyState == 4 && xml.status == 200) {
        var responeData = xml.responseText;
        var data = JSON.parse(responeData);
    } else {
        // 處理異常
    }
};

xml.send('account=1&password=123456');

複製代碼

這種方法能夠實現,可是對用戶體驗會有比較大的影響,而且在http協議最新的提案中,有考慮剔除請求同步標準spa

二、使用navigator中的sendBeacon發送異步請求(建議)

相關使用方法

body = JSON.stringify(body);
// 原來是 xhr.send(body)變爲
navigator.sendBeacon(url,body);

複製代碼

支持發送的body能夠是ArrayBufferView, Blob, DOMString, 或者 FormData 類型的數據。 根據MDN的介紹:

主要用於知足 統計和診斷代碼的須要,這些代碼一般嘗試在卸載(unload)文檔以前向web服務器發送數據。過早的發送數據可能致使錯過收集數據的機會。然而, 對於開發者來講保證在文檔卸載期間發送數據一直是一個困難。由於用戶代理一般會忽略在卸載事件處理器中產生的異步 XMLHttpRequest 。

複製代碼

下面介紹一下兩種其餘不一樣類型的發送方式

  • (1) body使用Blob對象,有個好處是,能夠自定義的設置header
blob = new Blob([`accoutn=12332323`], {type : 'application/x-www-form-urlencoded'});
navigator.sendBeacon("/leave", blob);

複製代碼
  • (2) 使用FormData對象,可是這時content-type會被自動變成"multipart/form-data"
var fd = new FormData();
fd.append('account', 123);
navigator.sendBeacon("/leave", fd);
複製代碼

三、服務端實現接收

=-=結束語:經過以上兩種結合,能夠在頁面結束時候,進行Ajax請求的發送=-=

原文參考相關連接:juejin.im/post/5c7e54…

相關文章
相關標籤/搜索