在某些情况下,我们可能有这样的需求,在跳转或离开当前页面时发送一个HTTP请求。如何确保请求能如我们意料的那样发送出去
eg: 在点击a标签跳转时,发送一个请求.
下面两种方式咋一看是同步的,但实际上请求却没有发送成功。浏览器测试时切换3G网络模式即可看到 network 信息
1 | // 方式 1 |
为什么没有请求成功?
以下是 Google对特定生命周期状态的总结:
一旦页面开始被浏览器卸载并从内存中清除,页面就处于终止状态。在这种状态下没有新的任务可以启动,并且正在进行的任务如果运行时间过长可能会被杀死。
简而言之,浏览器的设计假设当一个页面被关闭时,没有必要继续处理它排队的任何后台进程。
解决的方案
async/await
可以使用处理异步的方式,但是这种方式会损害用户体验,如果接口请求时间过长的话
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17document.getElementById('link').addEventListener('click', async (e) => {
e.preventDefault();
// Wait for response to come back...
await fetch("/log", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
some: 'data'
}),
});
// ...and THEN navigate away.
window.location = e.target.href;
});使用 Fetch 的 keepalive
keepalive 会让请求保持打开状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<a href="/some-other-page" id="link">Go to Page</a>
<script>
document.getElementById('link').addEventListener('click', (e) => {
fetch("/log", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
some: "data"
}),
keepalive: true
});
});
</script>使用
Navigator.sendBeacon()
该
Navigator.sendBeacon()
函数专门用于发送单向请求简单示例:
navigator.sendBeacon(‘/log’, JSON.stringify({ some: “data” }));
1
2
3
4
5
6
7
8
9<a href="/some-other-page" id="link">Go to Page</a>
<script>
document.getElementById('link').addEventListener('click', (e) => {
// 此方法不支持 修改 contentType: application/json. 采用下面方式
const blob = new Blob([JSON.stringify({ some: "data" })], { type: 'application/json; charset=UTF-8' });
navigator.sendBeacon('/log', blob));
});
</script>请求以 Lowest 最低优先级方式 发送。换句话说,
sendBeacon()
确保它的请求不会妨碍那些对您的应用程序和用户体验真正重要的请求。ping 属性
现在越来越多的 浏览器 支持 ping 属性。当附加链接时,会触发一个 post 请求
此方式 传参不方便, 火狐默认不打开此功能
1
2
3<a href="http://localhost:3000/other" ping="http://localhost:3000/log">
Go to Other Page
</a>
- 本文作者: 王不留行
- 本文链接: https://wyf195075595.github.io/2022/06/24/programming/javascript/用户离开页面时发送请求/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!