在使用者重新整理、跳轉或關閉瀏覽器時向伺服器傳送統計資料,前端開發中常用的方法有以下幾種:
1. 使用navigator.sendBeacon()
API:
這是最推薦的方式,尤其是在使用者即將離開頁面時。sendBeacon()
方法非同步傳送少量資料到伺服器,並且不會阻塞頁面解除安裝或影響下一個導航的載入效能。它在瀏覽器後臺傳送資料,即使瀏覽器已經關閉,也能保證資料儘可能地傳送到伺服器。
window.addEventListener('unload', logData);
function logData() {
if (navigator.sendBeacon) {
navigator.sendBeacon('/log', JSON.stringify({/* 資料 */}));
} else {
// sendBeacon() 不支援時的 fallback,例如使用同步 XMLHttpRequest
// 但要注意這可能會阻塞頁面解除安裝
var xhr = new XMLHttpRequest();
xhr.open('POST', '/log', false); // 使用同步請求
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({/* 資料 */}));
}
}
2. 使用XMLHttpRequest
(同步):
在unload
或beforeunload
事件中使用同步的XMLHttpRequest
傳送資料。這種方法的缺點是會阻塞頁面解除安裝,影響使用者體驗,並且在某些瀏覽器中可能不被支援或受到限制。 因此,不推薦使用,除非sendBeacon
不可用。
window.addEventListener('unload', logData); // 或 beforeunload
function logData() {
var xhr = new XMLHttpRequest();
xhr.open('POST', '/log', false); // 同步請求
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({/* 資料 */}));
}
3. 使用fetch
API (keepalive):
fetch
API 的 keepalive
選項允許在頁面解除安裝後繼續傳送請求。這在支援的瀏覽器中可以作為 sendBeacon
的替代方案。
window.addEventListener('unload', logData);
async function logData() {
try {
await fetch('/log', {
method: 'POST',
body: JSON.stringify({/* 資料 */}),
keepalive: true
});
} catch (error) {
// 處理錯誤
}
}
4. 使用 Image 物件 (畫素追蹤):
建立一個 Image 物件,並將其 src
屬性設定為指向伺服器上的一個記錄日誌的指令碼,可以在 URL 中攜帶資料。這種方法的缺點是隻能傳送 GET 請求,並且資料量有限。
window.addEventListener('unload', logData);
function logData() {
new Image().src = `/log?data=${encodeURIComponent(JSON.stringify({/* 資料 */}))`;
}
事件選擇:
unload
: 頁面完全解除安裝時觸發。此時文件、資源都已經被移除。由於頁面正在解除安裝,執行時間有限,建議使用sendBeacon
。beforeunload
: 在頁面解除安裝前觸發,可以取消解除安裝。如果在該事件處理函式中返回一個非空字串,瀏覽器會顯示一個確認對話方塊,詢問使用者是否要離開頁面。 要注意的是,在移動端瀏覽器中,beforeunload
事件可能不被支援或行為不一致。
資料格式:
建議使用 JSON 格式來傳送資料,方便伺服器端處理。
伺服器端:
伺服器端需要設定相應的路由來接收和處理這些資料。
總結:
navigator.sendBeacon()
是目前最好的選擇,因為它不會阻塞頁面解除安裝,並且能夠保證資料儘可能地傳送到伺服器。如果瀏覽器不支援 sendBeacon
,可以考慮使用 fetch
with keepalive
,最後才考慮使用同步的 XMLHttpRequest
或 Image 物件。 選擇哪種方法取決於你的具體需求和瀏覽器相容性要求。 記住測試不同瀏覽器和場景下的相容性。