- 原文地址:Logging Activity With The Web Beacon API
- 原文做者:Drew
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:Elliott Zhao
- 校對者:Eternaldeath, StellaBauhinia
Beacon API是一種從網頁把信息傳遞給服務器的輕量而且高效的方法。咱們來了解一下如何使用它,以及它與傳統的 Ajax 技術有何不一樣。前端
Beacon API 是一個基於 JavaScript 的 Web API,用於將少許數據從瀏覽器發送到 Web 服務器,而無需等待響應。在本文中,咱們將介紹它能夠用在哪些場景,它和其餘相似的技術,如 XMLHTTPRequest
(‘Ajax’) 有何不一樣,以及如何開始使用它。android
若是您知道爲何要使用 Beacon,你能夠隨時直接跳到入門部分。ios
Beacon API用於將少許數據發送到服務器,而無需等待響應。後一部分是關鍵,指出了爲什麼 Beacon 如此有用 —— 咱們的代碼毫不須要處理響應,即便服務器發送了一個。Beacon 專門用於發送數據而後忘記它。我本並不期待一個響應,並且咱們也不會獲得響應。git
能夠把它想象成度假時發回家的明信片。你把少許數據放在上面(有點相似於「真但願你也在這」和「天氣真好」),把它放進信箱,你不會期待迴應。沒有人會給明信片回信說「是呀,我但願我真的在那兒,很是感謝!」github
對於現代網站和應用,有不少用例正巧能夠被歸類進這種發送即忘記的處理模式。web
讓這個過程表現得剛剛好並非個簡單的任務。這就是爲何咱們設置**「我這樣工做」的會話** —— 智能 cookie 共享取得了很好的效果。固然,這是 Smashing 會員服務的一部分。後端
大多數人想到的第一個用例是分析。像 Google Analytics 這樣的大型解決方案可能會對頁面訪問等內容進行很好的概述,但若是咱們想要更加個性化的內容呢?咱們能夠編寫一些 JavaScript 來跟蹤頁面中發生的事情(多是用戶如何與組建交互,或者在遵從 CTA 建議以前閱讀過哪篇文章),然而咱們還須要在用戶離開頁面的時候發送這些數據到服務器。Beacon 能夠完美作到這一點,由於咱們只是記錄數據而不須要響應。api
咱們沒有理由不能涵蓋一般交給 Google Analytics 處理的那些普通任務,基於用戶自己和他們的設備與瀏覽器的功能上報數據。若是用戶登陸了會話,你甚至能夠把這些統計信息綁定到已知的我的。不管您收集什麼數據,均可以使用 Beacon 將其發送回服務器。瀏覽器
此行爲的另外一種有用的應用是從 JavaScript 代碼中記錄信息。假設你的頁面上有一個複雜的交互組件,能夠完美的經過全部的測試,可是在生產環境上偶爾失敗。你知道出現了失敗,可是你沒有辦法看到錯誤信息,從而開始調試。若是您能夠從代碼中嗅探到失敗自己,則能夠收集診斷信息並使用 Beacon 將其所有發回以進行記錄。安全
實際上,任何日誌任務均可以使用 Beacon 執行,例如在遊戲中建立存檔點,收集有關功能使用的信息,或記錄多變量測試的結果。若是您但願服務器知道在瀏覽器中發生的某件事,那麼 Beacon 多是(完成此需求)的一個有力備選。
我知道你在想什麼。沒有任何新東西,不是麼?十多年來,咱們已經可以使用 XMLHTTPRequest
從瀏覽器與服務器進行通訊。近期咱們又有了 Fetch API, 使用了更現代的,基於 Promise 的接口作到近乎同樣的事。既然如此,拿咱們爲何須要 Beacon API 呢?
這裏的關鍵是由於咱們沒有獲得響應,瀏覽器能夠排隊請求併發送它,非阻塞執行任何其餘代碼。就瀏覽器而言,不管咱們的代碼是否仍在運行,或者代碼執行到哪都不重要,由於沒有什麼能夠返回的,它能夠直接把 HTTP 請求轉到後臺,直到方便發送的時候。
這可能意味着要等待 CPU 負載較低,或網絡空閒,或者在可能的狀況下直接發送。重要的是瀏覽器將 Beacon 排隊並當即返回控制。它在發送 Beacon 的時候不會誤事。
要理解爲何這是一個了不起的事,咱們須要看看如何和怎樣從咱們的代碼發出這種請求。以咱們的分析日誌腳本爲例。咱們的代碼可能會計算用戶在頁面上花費的時間,所以在最後一刻將數據發送回服務器變得相當重要。當用戶要離開頁面的時候,咱們但願中止計時器而且把數據送回家。
通常來說,你應該使用 unload
或者 beforeunload
事件來執行日誌。這些事件會在用戶作出相似點擊鏈接導航到其餘頁面這種操做的時候觸發。這裏有個問題,在某個 unload
事件上運行的代碼會阻塞執行而且延遲頁面的卸載。若是頁面卸載被延遲,那麼加載下一個頁面也會被延遲,所以體驗上會感受很遲鈍。
你要記得 HTTP 請求到底有多慢。若是您正在考慮性能,一般您嘗試減小的主要因素之一是額外的 HTTP 請求,由於向網絡發送請求並得到響應可能會超級慢。你最不想作的事就是把這個耗時操做放在激活連接和開始請求下一個頁面之間。
Beacon 經過不阻塞的把請求排隊,即刻把控制權交還給你的代碼的方式處理這一點。而後瀏覽器負責在後臺不阻塞地發送該請求。這使得一切都快得多,這讓用戶更高興,也讓咱們都保住了工做。
所以,咱們瞭解 Beacon 是什麼,以及爲何咱們要用到它,因此讓咱們從一些代碼開始。基礎簡單到不能再簡單:
let result = navigator.sendBeacon(url, data);
複製代碼
結果是 boolean,若是瀏覽器接受而且把請求排隊了則返回 true
,若是在這個過程當中出現了問題就返回 false
。
navigator.sendBeacon()
navigator.sendBeacon
接受兩個參數。第一個參數是請求的 URL。請求做爲 HTTP POST 執行,發送在第二個參數中提供的任何數據。
數據參數能夠是多種格式中的任何一種,這些是直接從 Fetch API 中拿過來的。能夠是一個 Blob
,一個 BufferSource
,FormData
或者 URLSearchParams
—— 基本上是使用 Fetch 建立請求時使用的任何請求體類型。
對於基礎的鍵值數據,我喜歡使用 FormData
,由於它不復雜也很容易讀回。
// 將數據發送目標 URL
let url = '/api/my-endpoint';
// 建立一個新的 FormData 並添加一個鍵值對
let data = new FormData();
data.append('hello', 'world');
let result = navigator.sendBeacon(url, data);
if (result) {
console.log('Successfully queued!');
} else {
console.log('Failure.');
}
複製代碼
瀏覽器對 Beacon 的支持很好,惟一值得注意的例外是 Internet Explorer(在 Edge 中能用)和 Opera Mini。對於大部分的用法,應該均可以運行,但在使用 navigator.sendBeacon
以前對(瀏覽器)的支持性進行測試也是值得的。
很簡單就能作到:
if (navigator.sendBeacon) {
// Beacon 代碼
} else {
// 沒有 Beacon或許能夠回退到 XHR?
}
複製代碼
若是 Beacon 不可用,並且這個請求很重要,你能夠回退到 XHR 等阻塞方法。取決於你的受衆和目標,你一樣能夠選擇不理會。
爲了在實踐中理解,讓咱們建立一個基本的系統來記錄用戶停留在頁面上的時間。當頁面加載時,咱們會記錄下時間,當用戶離開頁面時,咱們將發送開始時間和當前時間到服務器。
因爲咱們只關心所花費的時間(而不是實際的時間),因此咱們可使用 performance.now()
來得到頁面加載時的基本時間戳。
let startTime = performance.now();
複製代碼
若是咱們把日誌放到一個函數中,咱們能夠在頁面卸載時調用它。
let logVisit = function() {
// 測試咱們擁有 Beacon 支持
if (!navigator.sendBeacon) return true;
// 數據發送的URL的例子
let url = '/api/log-visit';
// 要發送的數據
let data = new FormData();
data.append('start', startTime);
data.append('end', performance.now());
data.append('url', document.URL);
// 出發!
navigator.sendBeacon(url, data);
};
複製代碼
最後,當用戶離開頁面時,咱們須要調用這個函數。我本能地想使用 unload
事件,可是 Mac 上的 Safari 彷佛用安全警告阻止了請求,因此咱們在這邊使用 beforeunload
會更好一些。
window.addEventListener('beforeunload', logVisit);
複製代碼
當頁面卸載(或者立刻要卸載)的時候,咱們的 logVisit()
函數會被調用,若是瀏覽器支持 Beacon API 的話,咱們的 Beacon 就會被髮送。
(注意,若是沒有 Beacon 支持,咱們返回 true
,僞裝一切正常。返回 false
會取消事件而且終止頁面卸載。那就倒黴了。)
因爲 Beacon 的許多潛在用途都圍繞着活動跟蹤,我認爲,當咱們的日誌和跟蹤可能被綁定到用戶時,若是不提開發人員的社會責任和法律責任,那就過輕率了。
咱們能夠考慮最近歐洲的 GDPR 法案,它們和電子郵件有關,不過固然,這些法律也涉及任何形式的我的數據的存儲。若是你知道你的用戶是誰,而且能夠識別他們的會話,那麼你應該檢查你正在記錄的活動,以及它與你所聲明的用戶條款有何關係。
一般,咱們不須要像開發人員告訴咱們的那樣,跟蹤儘量多的數據。最好是故意不存儲能用來識別用戶的信息,而後減小把事情搞砸的可能性。
除了法律要求以外,大多數瀏覽器都有一個設置來容許用戶表達不想被跟蹤的意願。Do Not Track 會隨請求發送這樣一個 HTTP 報頭:
DNT: 1
複製代碼
若是您正在記錄能夠跟蹤特定用戶的數據,而且用戶發送了一個正數的 DNT
報頭,那麼最好遵循用戶的意願而且匿名化該數據,或者根本不跟蹤它。
例如,在PHP中,您能夠很容易地檢測這個報頭以下:
if (!empty($_SERVER['HTTP_DNT'])) {
// 用戶不想被跟蹤……
}
複製代碼
Beacon API 是從頁面返回數據到服務器的一種很是有用的方式,尤爲是對於日誌這種內容。瀏覽器支持很是普遍,它可使您無縫地記錄數據,而不會對用戶的瀏覽體驗和網站性能形成負面影響。請求的非阻塞性意味着性能比 XHR 和 Fetch 等替代方案好不少。
若是你想閱讀更多關於 Beacon API 的文章,下面的網站值得一看。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。