需求
这两天碰到一个需求:在用户刷新页面或者关闭页面的时候,前端要给后台发一条请求,释放该页面的授权占用。
分析了一下,这不就是在页面卸载时发请求嘛,三下五除二就实现一版:
window.addEventListener("beforeunload", () => { let oReq = new XMLHttpRequest(); oReq.open("POST", "http://127.0.0.1:1991/loginout"); oReq.send(JSON.stringify({name: "编程三昧"}));
测试发现:
- 刷新页面时基本满足需求(偶尔也会有后台接收不到请求的现象,但概率很低)
- 关闭页面时,后台接收不到请求
既然异步 Ajax 不行,那就试试同步的吧,结果直接报错了:
搜了一下,解释如下:
Chrome now disallows synchronous XHR during page dismissal when the page is being navigated away from or closed by the user. This involves the following events (when fired on the path of page dismissal): beforeunload, unload, pagehide, and visibilitychange.
概括起来就是:对现在的 Chrome 来说,在页面导航离开或者被用户关闭时,不允许发送同步 XHR 请求,涉及到的事件有:beforeunload、unload、pagehide 和 visibilitychange。
虽然问题没解决,但是却长知识了,这波不太亏!
navigator.sendBeacon()
后来通过搜索,看到有一个接口是专门来干这事的,那就是 navigator.sendBeacon()
。
描述
这个方法主要用于满足统计和诊断代码的需要,这些代码通常尝试在卸载(unload)文档之前向web服务器发送数据。
语法
navigator.sendBeacon(url, data);
参数
url
表明data
将要被发送到的网络地址。data
参数是将要发送的ArrayBufferView
或Blob
、DOMString
或者FormData
类型的数据。
返回值
当用户代理成功把数据加入传输队列时,sendBeacon()
方法将会返回 true
,否则返回 false
。
实现
既然有了接口,那实现起来就简单了。
代码
window.addEventListener("beforeunload", (e) => { const data = {name: "编程三昧"}; window.navigator.sendBeacon("http://127.0.0.1:1991/loginout", JSON.stringify(data)); });
效果
不管是刷新页面还是关闭页面,后台都能接收到前端发送过来的请求,完美实现需求。
总结
浏览器现在功能越来越强大,支持的 API 也越来越丰富,放在之前很难实现的功能,现在可能就是轻而易举的事,还是要多关注技术动态。
~本文完,感谢阅读!
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
你来,怀揣期望,我有墨香相迎! 你归,无论得失,唯以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!