改善同步 XMLHttpRequest() 中的網頁關閉問題

減少延遲導航

喬梅利
Joe Medley

使用者關閉時,網頁或應用程式經常會有未提交的數據分析或其他資料。為避免資料遺失,部分網站會使用對 XMLHttpRequest() 的同步呼叫,保持網頁或應用程式開啟,直到資料傳送到伺服器為止。此技術不僅提供更好的儲存資料的方法,還包括延遲關閉頁面數秒,造成使用者體驗不佳。

這種做法需要改變,瀏覽器也會不斷回應。XMLHttpRequest() 規格已預定淘汰及移除。Chrome 80 第一個步驟是禁止多個事件處理常式內的同步呼叫,特別是 beforeunloadunloadpagehidevisibilitychange 以關閉程序觸發時。WebKit 最近也提議實行相同行為變更的修訂版本

本文將簡單說明需要時間更新網站的使用者,並概述 XMLHttpRequest() 的替代方案。

暫時選擇不採用

Chrome 不希望只是將外掛程式提取 XMLHttpRequest(),因此還有幾種暫時性的停用選項可供使用。網際網路上的網站則提供來源試用。如此一來,您就可以在網頁標頭中加入來源專屬權杖,藉此啟用同步 XMLHttpRequest() 呼叫。這個選項很快就會在 Chrome 89 出貨前結束,約為 2021 年 3 月。Enterprise Chrome 客戶也可以使用同時結束的 AllowSyncXHRInPageDismissal 政策旗標。

替代方案

無論您採用何種方式將資料傳回伺服器,最好避免等待頁面解除載入後,一次傳送所有資料。除了打造不良的使用者體驗外,新式瀏覽器也無法執行卸載,如果發生問題,可能會導致資料遺失。具體來說,卸載事件通常不會在行動瀏覽器上觸發 因為在沒有unload事件觸發的情況下,行動作業系統上有許多方式關閉分頁或瀏覽器 使用 XMLHttpRequest() 時,可以選擇使用小型酬載。不過,這是個必要條件根據規格要求,這兩種替代品項的上傳限制皆為 64 KB。

擷取保持運作

Fetch API 提供穩固的方法可以處理伺服器互動,並提供一致的介面,以供跨不同的平台 API 使用。您可以利用 keepalive 的選項,確保要求啟動的網頁無論是否保持開啟狀態,仍能繼續處理要求:

window.addEventListener('unload', {
  fetch('/siteAnalytics', {
    method: 'POST',
    body: getStatistics(),
    keepalive: true
  });
}

fetch() 方法可讓您進一步控管傳送到伺服器的內容。此範例並未顯示,fetch() 也會傳回透過 Response 物件解析的承諾。我打算離開網頁的卸載,因此選擇不做任何處理。

SendBeacon()

SendBeacon() 實際上會在背景使用 Fetch API,因此,兩者的 64 KB 酬載限制相同,也是為什麼還能確保要求在頁面卸載後繼續執行。它的主要優勢在於簡單。只要使用一行程式碼即可提交資料:

window.addEventListener('unload', {
  navigator.sendBeacon('/siteAnalytics', getStatistics());
}

結語

隨著更多瀏覽器能使用 fetch(),我們希望能在某個時間點從網路平台中移除 XMLHttpRequest()。瀏覽器供應商同意移除程式碼,但需要時間。要改善所有人的使用者體驗,第一步就是淘汰其中一個最糟的用途。

相片來源:Matthew HamiltonUnsplash 網站上