项目场景:
用户在离开页面时,发送http请求给后端,用来收集用户日志数据进行业务分析
问题描述
在浏览器内多页面发生跳转时,无法保证当前页面进程内的请求能够顺利完成,大多数情况下会被浏览器cancled, 请求不能到达后端服务器。
这些http请求能否成功依赖于下面几点:网络连接速度、应用程序性能、甚至于外部服务器本身的配置,可以尝试用下面代码解决
javascript
document.getElementById('link').addEveentListener('click', (e) => {
e.perventDefault();
fetch("/log", {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "123"
})
})
window.location = e.target.href;
})
但 fetch 会被加入异步队列,页面跳转时队列中剩余的请求仍会被 cancled。
那我们等待请求完成之后再 location 不就行了吗?
javascript
document.getElementById('link').addEveentListener('click', async(e) => {
e.perventDefault();
await fetch("/log", {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "123"
})
})
window.location = e.target.href;
})
上述代码貌似可以,但是在移动端300ms延迟都能明显感受,万一接口返回太慢,用户就会觉得网站很卡
解决方案:
好在目前前端浏览器都是现代浏览器, fetch提供了 keeplive 参数来处理这个问题:
javascript
document.getElementById('link').addEveentListener('click', (e) => {
fetch("/log", {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "123"
}),
keepalive: true // 设置保持请求
})
})
使用keepalive 不需要我们阻止默认行为,也不需要 location 跳转。就可以使这个请求发出去
另外
在axios 中也可以设置 keepalive,具体配置如下
是的,如果您创建自己的 axios 实例,您可以使用 axios 执行此操作。
javascript
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'},
httpAgent: new http.Agent({ keepAlive: true }),
});