動態

詳情 返回 返回

JS Navigator.sendBeacon 可靠的、異步地向服務器發送數據 - 動態 詳情

JS Navigator.sendBeacon 可靠的、異步地向服務器發送數據

前言

我們在上一篇頁面訪問&頁面關閉數據上報的文章中使用了 sendBeacon 方法用來發送數據,上篇文章是簡單使用,那本篇文章我們就詳細瞭解下這個東西。

一、Navigator.sendBeacon 是什麼&能做什麼?

Navigator.sendBeacon 是一個用於發送少量數據到服務器的 API,尤其適用於在頁面即將卸載時發送數據,如日誌記錄、用户行為分析等。

與傳統的 AJAX 請求不同,sendBeacon 方法的設計目標是確保數據在頁面卸載(例如用户關閉標籤頁或導航到新頁面)時能夠可靠地發送。

Navigator.sendBeacon 方法可用於通過 HTTP POST 將少量數據異步傳輸到 Web 服務器。

它主要用於將統計數據發送到 Web 服務器,同時避免了用傳統技術(如:XMLHttpRequest)發送分析數據的一些問題。

所以上篇文章在頁面關閉進行數據上報的時候,我們就選擇了 navigator.sendBeacon 方法。

二、Navigator.sendBeacon 詳細介紹

1、使用場景

  1. 頁面卸載時的日誌記錄:在用户離開頁面時記錄行為數據,如頁面停留時間、點擊行為等。
  2. 分析和監控:發送用户行為數據到分析服務器,用於網站性能監控和用户行為分析。
  3. 狀態報告:向服務器報告應用程序狀態或錯誤信息。

2、不使用 Navigator.sendBeacon 時,如何處理?

  1. 發起一個同步 XMLHttpRequest 來發送數據(open() 方法的第三個參數為 false)。
  2. 創建一個 <img> 元素並設置 src,大部分用户代理會延遲卸載(unload)文檔以加載圖像。
  3. 創建一個幾秒的 no-op 循環。

3、不使用 Navigator.sendBeacon 可能會帶來哪些問題?

3.1. 同步 XHR
  1. 同步請求會阻塞瀏覽器的主線程,導致頁面在請求完成之前無法響應用户操作。這會嚴重影響用户體驗,尤其是在請求需要較長時間才能完成時。
  2. 許多現代瀏覽器會對同步請求發出警告,提示開發者這種方法可能會導致性能問題,並建議改用異步請求。
3.2. 創建 img 元素
  1. 頁面卸載流程被阻塞。
  2. 後面頁面的加載時機被延遲,用户體驗不好。
3.3. 創建循環
  1. 頁面卸載流程被阻塞。
  2. 後面頁面的加載時機被延遲,用户體驗不好。

4、Navigator.sendBeacon 的優點

  1. 可靠性:sendBeacon 的主要設計目標是確保數據在頁面卸載時能夠可靠地發送。瀏覽器會在後台繼續嘗試發送數據,即使頁面已經關閉或正在導航到新頁面。
  2. 非阻塞:sendBeacon 方法是非阻塞的,不會阻礙頁面的卸載過程。相比於傳統的同步 AJAX 請求,不會影響用户體驗或導致頁面卸載延遲。
  3. 簡單性:接口簡單,只需提供目標 URL 和數據,無需處理響應。適用於只需要發送數據而不需要從服務器獲取數據的場景。
  4. 安全性:與其他 AJAX 請求方法一樣,sendBeacon 遵循同源策略,不能發送跨域請求,除非服務器設置了適當的 CORS 頭。

5、使用限制

  1. 數據大小限制(通常為幾十 KB),適用於發送少量數據。
  2. 因為數據大小有限,sendBeacon 不適合用於發送大量或大文件的數據。
  3. sendBeacon 方法始終使用 HTTP POST 請求。
  4. 不返回響應,不提供處理服務器響應的機制,無法檢查請求是否成功以及服務器的返回結果。

6、瀏覽器兼容性

Navigator.sendBeacon 支持主流的現代瀏覽器,包括 ChromeFirefoxSafariEdge 等,但不支持較老的瀏覽器(如 IE 11 及更早版本)。

image

三、Navigator.sendBeacon 如何使用

1、語法

navigator.sendBeacon(url);
navigator.sendBeacon(url, data);

2、參數

2.1. url

url 參數表明 data 將要被髮送到的網絡地址。

2.2. data 可選

data 參數是將要發送的 ArrayBufferArrayBufferViewBlobDOMStringFormDataURLSearchParams 類型的數據。

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、相同點

  1. 發送網絡請求:所有這三種方法都用於從客户端向服務器發送數據。
  2. 支持多種數據格式:它們都可以發送字符串、JSON、二進制數據等多種格式的數據。

2、不同點

2.1. Navigator.sendBeacon
  1. 用於在頁面卸載時發送少量數據,適合日誌、分析數據等用途。
  2. 發送數據是異步的,但不返回任何信息給調用者,無法處理服務器的響應。
  3. 設計為在頁面卸載時保證數據發送,即使在瀏覽器關閉或頁面跳轉時。
  4. 始終使用 HTTP POST 請求。
  5. 不需要處理響應,使用簡單。
2.2. XMLHttpRequest
  1. 用於更復雜的、需要處理響應的 AJAX 請求。
  2. 可以進行同步或異步請求。
  3. 可以處理服務器的響應,並進行進一步處理(如解析 JSON、處理狀態碼等)。
  4. 提供豐富的事件(如 onloadonerroronprogress 等),可以監控請求的各個階段。
  5. 在所有主流瀏覽器中都得到了廣泛支持,包括一些較老的瀏覽器。
  6. 使用較複雜,需要處理請求的各個階段和狀態。
2.3. Fetch
  1. 現代化的請求接口,用於替代 XMLHttpRequest,支持更簡單和更靈活的請求和響應處理。
  2. 始終進行異步請求,返回 Promise 對象。
  3. 支持鏈式處理響應,可以輕鬆解析 JSON、處理狀態碼等。
  4. 支持 async/await 語法,更符合現代 JavaScript 開發習慣。
  5. 更好地支持跨域請求和 CORS(跨域資源共享)。
  6. 允許在請求中添加更多的選項(如自定義頭部、請求方法等)。

3、三者使用場景

  • Navigator.sendBeacon:簡單、適合在頁面卸載時發送少量數據,不處理響應。
  • XHR:功能全面、適合複雜的 AJAX 請求,但使用較複雜。
  • Fetch:現代化接口,簡潔靈活,適合處理複雜請求和響應。

五、總結

  1. Navigator.sendBeacon 是一個專為可靠性設計的 API,特別適用於在頁面卸載時發送少量數據。
  2. 它具有簡單、非阻塞、可靠等優點,特別適合日誌記錄和用户行為分析等場景。
  3. 發出的是異步請求,並且是 POST 請求。
  4. 只能判斷出是否放入瀏覽器任務隊列,不能判斷是否發送成功。
  5. 無需處理返回值。
  6. 需要注意瀏覽器兼容問題。

引用

user avatar zzd41 頭像 beverly0 頭像 dengzhanyong 頭像 wosign 頭像 hlinleanring 頭像 beiniaonanyou 頭像 qiangjiandebinggan 頭像 lizh 頭像 xiaomogu_5f2124ad3ad42 頭像
點贊 9 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.