JS Navigator.sendBeacon 可靠的、異步地向服務器發送數據
前言
我們在上一篇頁面訪問&頁面關閉數據上報的文章中使用了 sendBeacon 方法用來發送數據,上篇文章是簡單使用,那本篇文章我們就詳細瞭解下這個東西。
一、Navigator.sendBeacon 是什麼&能做什麼?
Navigator.sendBeacon 是一個用於發送少量數據到服務器的 API,尤其適用於在頁面即將卸載時發送數據,如日誌記錄、用户行為分析等。
與傳統的 AJAX 請求不同,sendBeacon 方法的設計目標是確保數據在頁面卸載(例如用户關閉標籤頁或導航到新頁面)時能夠可靠地發送。
Navigator.sendBeacon 方法可用於通過 HTTP POST 將少量數據異步傳輸到 Web 服務器。
它主要用於將統計數據發送到 Web 服務器,同時避免了用傳統技術(如:XMLHttpRequest)發送分析數據的一些問題。
所以上篇文章在頁面關閉進行數據上報的時候,我們就選擇了 navigator.sendBeacon 方法。
二、Navigator.sendBeacon 詳細介紹
1、使用場景
- 頁面卸載時的日誌記錄:在用户離開頁面時記錄行為數據,如頁面停留時間、點擊行為等。
- 分析和監控:發送用户行為數據到分析服務器,用於網站性能監控和用户行為分析。
- 狀態報告:向服務器報告應用程序狀態或錯誤信息。
2、不使用 Navigator.sendBeacon 時,如何處理?
- 發起一個同步
XMLHttpRequest來發送數據(open()方法的第三個參數為false)。 - 創建一個
<img>元素並設置src,大部分用户代理會延遲卸載(unload)文檔以加載圖像。 - 創建一個幾秒的
no-op循環。
3、不使用 Navigator.sendBeacon 可能會帶來哪些問題?
3.1. 同步 XHR
- 同步請求會阻塞瀏覽器的主線程,導致頁面在請求完成之前無法響應用户操作。這會嚴重影響用户體驗,尤其是在請求需要較長時間才能完成時。
- 許多現代瀏覽器會對同步請求發出警告,提示開發者這種方法可能會導致性能問題,並建議改用異步請求。
3.2. 創建 img 元素
- 頁面卸載流程被阻塞。
- 後面頁面的加載時機被延遲,用户體驗不好。
3.3. 創建循環
- 頁面卸載流程被阻塞。
- 後面頁面的加載時機被延遲,用户體驗不好。
4、Navigator.sendBeacon 的優點
- 可靠性:
sendBeacon的主要設計目標是確保數據在頁面卸載時能夠可靠地發送。瀏覽器會在後台繼續嘗試發送數據,即使頁面已經關閉或正在導航到新頁面。 - 非阻塞:
sendBeacon方法是非阻塞的,不會阻礙頁面的卸載過程。相比於傳統的同步AJAX請求,不會影響用户體驗或導致頁面卸載延遲。 - 簡單性:接口簡單,只需提供目標
URL和數據,無需處理響應。適用於只需要發送數據而不需要從服務器獲取數據的場景。 - 安全性:與其他
AJAX請求方法一樣,sendBeacon遵循同源策略,不能發送跨域請求,除非服務器設置了適當的CORS頭。
5、使用限制
- 數據大小限制(通常為幾十
KB),適用於發送少量數據。 - 因為數據大小有限,
sendBeacon不適合用於發送大量或大文件的數據。 sendBeacon方法始終使用HTTP POST請求。- 不返回響應,不提供處理服務器響應的機制,無法檢查請求是否成功以及服務器的返回結果。
6、瀏覽器兼容性
Navigator.sendBeacon 支持主流的現代瀏覽器,包括 Chrome、Firefox、Safari、Edge 等,但不支持較老的瀏覽器(如 IE 11 及更早版本)。
三、Navigator.sendBeacon 如何使用
1、語法
navigator.sendBeacon(url);
navigator.sendBeacon(url, data);
2、參數
2.1. url
url 參數表明 data 將要被髮送到的網絡地址。
2.2. data 可選
data 參數是將要發送的 ArrayBuffer、ArrayBufferView、Blob、DOMString、FormData 或 URLSearchParams 類型的數據。
3、返回值
類型:boolean
當用户代理成功把數據加入傳輸隊列時,sendBeacon() 方法將會返回 true,否則返回 false。
4、Navigator.sendBeacon 使用舉例
4.1. 參數格式為 ArrayBuffer
適用於傳遞二進制數據,如文件或圖像片段。
const buffer = new ArrayBuffer(8);
navigator.sendBeacon('/log', buffer);
4.2. 參數格式為 ArrayBufferView
ArrayBufferView 是一種表示二進制數據視圖的類型。常見的 ArrayBufferView 類型包括 Uint8Array, Int8Array, Uint16Array, Int16Array, Uint32Array, Int32Array, Float32Array, Float64Array 等等。
// 創建一個包含字符串的 Uint8Array
const text = 'Hello, world!';
const textEncoder = new TextEncoder();
const textArray = textEncoder.encode(text); // 將字符串編碼為 Uint8Array
// 創建一個包含其他二進制數據的 Uint8Array
const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
// 將兩部分數據合併到一個大的 Uint8Array
const combinedArray = new Uint8Array(textArray.length + binaryData.length);
combinedArray.set(textArray, 0);
combinedArray.set(binaryData, textArray.length);
// 發送合併後的 Uint8Array
navigator.sendBeacon('xxx/xxx', combinedArray);
4.3. 參數格式為 Blob
適用於傳遞文件或其他大塊的二進制數據。
const blob = new Blob(['user=gqk'], { type: 'text/plain' });
navigator.sendBeacon('xxx/xxx', blob);
4.4. 參數格式為 DOMString
適用於簡單的文本數據。
navigator.sendBeacon('xxx/xxx', 'this is sendBeacon case');
4.5. 參數格式為 FormData
適用於發送表單內容或複雜的鍵值對數據。
const formData = new FormData();
formData.append('user', 'gqk');
navigator.sendBeacon('xxx/xxx', formData);
4.6. 參數格式為 URLSearchParams
適用於發送 URL 編碼的查詢參數。
const params = new URLSearchParams();
params.append('user', 'gqk');
navigator.sendBeacon('xxx/xxx', params);
四、Navigator.sendBeacon 和 XHR、fetch 有什麼異同點
1、相同點
- 發送網絡請求:所有這三種方法都用於從客户端向服務器發送數據。
- 支持多種數據格式:它們都可以發送字符串、
JSON、二進制數據等多種格式的數據。
2、不同點
2.1. Navigator.sendBeacon
- 用於在頁面卸載時發送少量數據,適合日誌、分析數據等用途。
- 發送數據是異步的,但不返回任何信息給調用者,無法處理服務器的響應。
- 設計為在頁面卸載時保證數據發送,即使在瀏覽器關閉或頁面跳轉時。
- 始終使用
HTTPPOST請求。 - 不需要處理響應,使用簡單。
2.2. XMLHttpRequest
- 用於更復雜的、需要處理響應的
AJAX請求。 - 可以進行同步或異步請求。
- 可以處理服務器的響應,並進行進一步處理(如解析
JSON、處理狀態碼等)。 - 提供豐富的事件(如
onload、onerror、onprogress等),可以監控請求的各個階段。 - 在所有主流瀏覽器中都得到了廣泛支持,包括一些較老的瀏覽器。
- 使用較複雜,需要處理請求的各個階段和狀態。
2.3. Fetch
- 現代化的請求接口,用於替代
XMLHttpRequest,支持更簡單和更靈活的請求和響應處理。 - 始終進行異步請求,返回
Promise對象。 - 支持鏈式處理響應,可以輕鬆解析
JSON、處理狀態碼等。 - 支持
async/await語法,更符合現代JavaScript開發習慣。 - 更好地支持跨域請求和
CORS(跨域資源共享)。 - 允許在請求中添加更多的選項(如自定義頭部、請求方法等)。
3、三者使用場景
Navigator.sendBeacon:簡單、適合在頁面卸載時發送少量數據,不處理響應。XHR:功能全面、適合複雜的AJAX請求,但使用較複雜。Fetch:現代化接口,簡潔靈活,適合處理複雜請求和響應。
五、總結
Navigator.sendBeacon是一個專為可靠性設計的API,特別適用於在頁面卸載時發送少量數據。- 它具有簡單、非阻塞、可靠等優點,特別適合日誌記錄和用户行為分析等場景。
- 發出的是異步請求,並且是
POST請求。 - 只能判斷出是否放入瀏覽器任務隊列,不能判斷是否發送成功。
- 無需處理返回值。
- 需要注意瀏覽器兼容問題。