当前位置:网站首页>页面关闭前,如何发送一个可靠请求
页面关闭前,如何发送一个可靠请求
2022-07-04 22:17:00 【swlws9527】

一、问题
从 A 页面进入到 B 页面前,向后台发送一个/log请求,如何保证这个请求一定会被接收并处理。
场景复现
function nextPage() {
fetch("/log", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
some: "data",
}),
});
window.location.href = "/other.html";
}
这段代码里,页面切换成功后,后台是接收不到/log请求的。原因:
- js 的执行可以认为分为
主线程、异步线程 - 当页面进入
terminated状态时,会释放所有的资源。也就是说,此时异步线程中未执行的上下文,不会再被处理。
二、解决方案
2.1 async/await
既然是因为异步导致的请求被执行,那改为同步即可。
async function nextPage() {
await fetch("/log", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
some: "data",
}),
});
window.location.href = "/other.html";
}
这种方式会阻塞代码执行
2.2 keepAlive
fetch中设置keepalive为true时,即使发起请求的页面处于terminated状态,也会保持连接。利用这哥特性,可以发送可靠的请求。
function nextPage() {
fetch("/log", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
some: "data",
}),
keepalive: true,
});
window.location.href = "/other.html";
}
2.3 navigator.sendBeacon
使用 sendBeacon() 方法会使用户代理在有机会时异步地向服务器发送数据,同时不会延迟页面的卸载或影响下一导航的载入性能,这意味着:
- 数据发送是可靠的。
- 数据异步传输。
- 不影响下一导航的载入。
代码示例:
function nextPage() {
navigator.sendBeacon(
"/log",
JSON.stringify({
some: "data",
})
);
window.location.href = "/other.html";
}
sendBeacon()API 不支持添加请求头,可以利用Blob做一些改动支持请求头
function nextPage() {
const blob = new Blob([JSON.stringify({
some: "data" })], {
type: "application/json; charset=UTF-8",
});
navigator.sendBeacon("/log", blob);
window.location.href = "/other.html";
}
需要注意的是,在Chrome的network面板下,它的文档类型为ping,不是常见的fetch、xhr类型。
2.4 <a>标签的 ping 属性
越来越多的厂商支持ping属性了。示例:
<a href="/other.html" ping="/log">other page</a>
点击a标签时,会额外发送一个请求/log,它的请求头中包含几个特殊的值:
{
"ping-from": "http://127.0.0.1:3000/",
"ping-to": "http://127.0.0.1:3000/other.html",
"content-type": "text/ping"
}
三、方案选择
如果出现以下情况,可以使用 fetch()+keepalive:
- 需要自定义请求头。
- 使用 GET 请求,不是 POST 请求。
- 支持较旧的浏览器(如 IE),并且已经加载了 fetch polyfill。
但如果满足以下条件,sendBeacon()可能是更好的选择:
- 进行简单的服务请求,不需要太多定制化。
- 更喜欢更干净、更优雅的 API。
- 希望保证您的请求不会与应用程序中发送的其他高优先级请求竞争。
参考:
边栏推荐
- [acwing] solution of the 58th weekly match
- 蓝队攻防演练中的三段作战
- 30余家机构联合发起数字藏品行业倡议,未来会如何前进?
- 微服务--开篇
- 力扣2_1480. 一维数组的动态和
- 华泰证券是国家认可的券商吗?开户安不安全?
- Tla+ introductory tutorial (1): introduction to formal methods
- Visual task scheduling & drag and drop | scalph data integration based on Apache seatunnel
- The Sandbox 和数字好莱坞达成合作,通过人力资源开发加速创作者经济的发展
- 傳智教育|如何轉行互聯網高薪崗比特之一的軟件測試?(附軟件測試學習路線圖)
猜你喜欢
随机推荐
TLA+ 入门教程(1):形式化方法简介
【OpenGL】笔记二十九、抗锯齿(MSAA)
Wake up day, how do I step by step towards the road of software testing
Common shortcut keys for hbuilder x
With this PDF, we finally got offers from eight major manufacturers, including Alibaba, bytek and Baidu
[the 2023 autumn recruitment of MIHA tour] open [the only exclusive internal push code of school recruitment eytuc]
Use blocconsumer to build responsive components and monitor status at the same time
Flask 上下文详解
Deployment of JVM sandbox repeater
Short video system source code, click the blank space of the screen, the keyboard does not automatically stow
Detailed explanation of flask context
如何实现轻松管理1500万员工?
UML diagram memory skills
制作条形码的手机App推荐
AscendEX 上线 Walken (WLKN) - 一款卓越领先的“Walk-to-Earn”游戏
Shell 脚本实现应用服务日志入库 Mysql
Logo special training camp Section V font structure and common design techniques
The Sandbox 和数字好莱坞达成合作,通过人力资源开发加速创作者经济的发展
Apachecn translation, proofreading, note sorting activity progress announcement 2022.7
sobel过滤器









