用 JavaScript Beacon 说再见
Hemath's Blog ☘️
Hemath's Blog ☘️
Sometimes we want to send a piece of data to our servers when user leaves our website or webapp. Maybe it’s for for analytics or even auto-logout when they leave the website. But do you know what is a reliable way of doing it?
有时我们希望在用户离开网站或 webapp 时向服务器发送一小段数据。也许是为了做分析,或者在他们离开网站时自动登出。但你知道有什么可靠的方法吗?
Most of you might say use XMLHTTPRequest (or fetch) in beforeunload
or unload
events. Like,
大多数人可能会说,在 beforeunload
或 unload
事件中使用 XMLHTTPRequest(或 fetch)。像这样:
window.addEventListener("beforeunload", () => {
fetch('/analytics', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({event: 'page_leave'})
})
});
Well, in my experience, this is not that reliable. Sometimes it works, sometimes it doesn’t. There must be a reliable way to do such a trivial task.
然而,根据我的经验,这种方式并不总是可靠。有时能成功,有时却不行。对于这样一个简单的任务,一定有一种更可靠的方法。
You might ask, why not we have an event listener for the browser tab? We can easily listen for that event and do our operations right?
你可能会问,为什么我们不监听浏览器标签页的事件?我们可以轻松地监听该事件并立即执行操作,对吧?
Because, users can leave your website by just changing the URL to some other website or clicking a bookmark. Don’t expect users to be polite :)
因为,用户只需把 URL 改成其他网站或点击书签就能离开你的网站。别指望用户会“礼貌”地离开 :)
But why beforeunload doesn’t work reliably? The reason is that browser cannot wait for some JavaScript to execute before moving on. It will be a bad experience for user to have delay when they close the tab or move to a different website. So it gives sometime and hardly stops the exeuction of JavaScript.
但为什么 beforeunload 并不可靠?原因是浏览器不能为了等待某些 JavaScript 执行而延迟下一步操作。如果用户关闭标签页或跳转到其他网站时出现延迟,体验会非常糟糕。因此浏览器只给一点点时间,并且几乎会立即终止 JavaScript 的执行。
So when we send an network request to our backend, there is a high chance that browser either will not send it or will cancel it.
因此,当我们向后端发送网络请求时,浏览器很可能不会发送它,或者会将其取消。
That’s where Beacon API in Javascript comes in handy. It is like, fire-and-forget. Browser doesn’t need to wait for anything, once the request is sent, the JavaScript executi...