當前位置: 妍妍網 > 碼農

終於等到你!JS全新API支持關閉頁面時安全發送網路請求

2024-03-28碼農

在日常的開發中,經常需要在使用者關閉頁面或導航至其他頁面時,向伺服器發送重要的數據請求。然而,確保這些數據請求能夠安全、完整地發送到後端一直是一個挑戰。近日,Chrome 瀏覽器正在積極引入一個革命性的 JavaScript API—— fetchLater() 。這個全新的 API 旨在徹底簡化關閉頁面時的數據發送過程,確保即使在頁面關閉後或使用者離開的情況下,請求也能在未來某個時刻被安全、可靠地發出。本文就來詳細了解這個超實用的全新 API。

註: fetchLater() 已在 Chrome 中提供,用於在版本 121(2024 年 1 月釋出)開始的原始試驗中供真實使用者測試,該試驗將持續到 Chrome 126(2024 年 7 月)。

以前這樣寫

在傳統的做法中,開發者常常依賴 pagehide visibilitychange unload beforeunload 事件來捕捉頁面解除安裝的時機,並借助 navigator.sendBeacon() 方法或使用帶有 keepalive 選項的 fetch() 來發送數據。

當頁面解除安裝時, pagehide 事件和 unload 事件會被觸發。同時, visibilitychange 事件會在頁面的可見性發生變化時觸發,這也可以用來捕捉頁面解除安裝的情況。當使用者即將離開當前頁面(例如,嘗試關閉瀏覽器分頁或重新整理頁面)時, beforeunload 事件被觸發。

window.addEventListener('pagehide',(event)=>{
sendDataToServer();
});
window.addEventListener('visibilitychange',(event)=>{
if(document.visibilityState ==='hidden'){
sendDataToServer();
}
});
addEventListener("unload",(event)=>{
sendDataToServer();
})
addEventListener("beforeunload",(event)=>{
sendDataToServer();
})

navigator.sendBeacon() 方法用於異步地向伺服器發送數據,即使頁面正在解除安裝或不可見,也能保證數據被發送。這對於確保數據能夠可靠地到達伺服器非常有用。

functionsendDataToServer(){
var url ='https://example.com/log';
var data =newBlob(['some data'],{type:'application/json'});
navigator.sendBeacon(url, data);
}

當然,也可以使用 fetch() keepalive 選項來確保請求在頁面解除安裝後繼續發送。不過需要註意的是, keepalive 選項的支持情況可能因瀏覽器而異。

functionsendDataToServer(){
var url ='https://example.com/log';
var data ={someKey:'someValue'};
fetch(url,{
method:'POST',
body:JSON.stringify(data),
headers:{
'Content-Type':'application/json'
},
keepalive:true// 嘗試在頁面解除安裝後繼續發送請求
});
}

然而, pagehide visibilitychange unload beforeunload 事件都存在可靠性問題。數據顯示,即使多個事件一起使用,大約有 10% 的數據沒有被發送就消失了。

妙用 fetchLater()

fetchLater() 的功能正如其名:它要求瀏覽器在未來某個時刻確保發送請求,即使頁面已經關閉或使用者導航到其他頁面。

fetchLater() 的語法如下:

const fetchLaterResult =fetchLater(request, options);

fetchLater() 接受兩個參數,與 fetch() 的參數相同:

  • request :可以是一個字串形式的 URL,或者是一個 Request 例項。

  • options :可選項,它擴充套件了 fetch() 中的 options ,並增加了一個名為 activateAfter 的超時設定。

  • fetchLater() 返回一個 FetchLaterResult 物件,它目前只包含一個唯讀內容 activated 。當指定的「稍後」時間點到來且請求已經發出時, activated 內容會被設定為 true 。需要註意的是,對於 fetchLater() 發出的請求,其任何響應都不會被保留。

    request

    在使用時,最簡單的形式是直接傳入一個 URL 作為請求:

    fetchLater('/endpoint/');

    並且, fetchLater() 繼承了 fetch() 的靈活性,允許使用者為其請求設定多種選項。這些選項包括自訂頭部資訊、控制憑據的處理方式、指定 POST 請求體,以及利用 AbortController 在必要時取消請求。

    fetchLater('/endpoint/',{
    method:'GET',
    cache:'no-store',
    mode:'same-origin',
    headers:{Authorization:'SUPER_SECRET'},
    });

    options

    fetchLater() options 參數擴充套件了 fetch() 的選項,新增了 activateAfter 超時設定,使得請求能夠在設定的超時時間後或頁面解除安裝時(兩者中較早發生者)自動觸發。

    例如,如果有一個套用,使用者通常會在整個工作日中保持開啟狀態。在這種情況下,您可以設定一個一小時的超時時間,以確保在分析數據時擁有更精細的粒度,同時確保即使使用者在這一小時內任何時候結束套用,也能夠成功發送數據。隨後,您可以為下一個小時的分析數據設定新的 fetchLater() 請求,以確保數據的持續收集和發送。

    const hourInMilliseconds =60*60*1000;
    fetchLater('/endpoint/',{activateAfter: hourInMilliseconds});

    嘗試 fetchLater()

    目前, fetchLater() 仍處於實驗狀態,現在可以在 chrome://flags/#enable-experimental-web-platform-features 中啟用 Experimental Web Platform 功能標誌來啟用 fetchLater() API。