- 原文地址: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、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。