在日常的开发中,经常需要在用户关闭页面或导航至其他页面时,向服务器发送重要的数据请求。然而,确保这些数据请求能够安全、完整地发送到后端一直是一个挑战。近日,Chrome 浏览器正在积极引入一个革命性的 JavaScript API——
fetchLater()
。这个全新的 API 旨在彻底简化关闭页面时的数据发送过程,确保即使在页面关闭后或用户离开的情况下,请求也能在未来某个时刻被安全、可靠地发出。本文就来详细了解这个超实用的全新 API。
注:
fetchLater()
已在 Chrome 中提供,用于在版本 121(2024 年 1 月发布)开始的原始试验中供真实用户测试,该试验将持续到 Chrome 126(2024 年 7 月)。
以前这样写
在传统的做法中,开发者常常依赖
pagehide
、
visibilitychange
、
unload
、
beforeunload
事件来捕捉页面卸载的时机,并借助
navigator.sendBeacon()
方法或使用带有
keepalive
选项的
fetch()
来发送数据。
当页面卸载时,
pagehide
事件和
unload
事件会被触发。同时,
visibilitychange
事件会在页面的可见性发生变化时触发,这也可以用来捕捉页面卸载的情况。当用户即将离开当前页面(例如,尝试关闭浏览器标签页或刷新页面)时,
beforeunload
事件被触发。
window.addEventListener('pagehide',(event)=>{
sendDataToServer();
});
window.addEventListener('visibilitychange',(event)=>{
if(document.visibilityState ==='hidden'){
sendDataToServer();
}
});
addEventListener("unload",(event)=>{
sendDataToServer();
})
addEventListener("beforeunload",(event)=>{
sendDataToServer();
})
navigator.sendBeacon()
方法用于异步地向服务器发送数据,即使页面正在卸载或不可见,也能保证数据被发送。这对于确保数据能够可靠地到达服务器非常有用。
functionsendDataToServer(){
var url ='https://example.com/log';
var data =newBlob(['some data'],{type:'application/json'});
navigator.sendBeacon(url, data);
}
当然,也可以使用
fetch()
的
keepalive
选项来确保请求在页面卸载后继续发送。不过需要注意的是,
keepalive
选项的支持情况可能因浏览器而异。
functionsendDataToServer(){
var url ='https://example.com/log';
var data ={someKey:'someValue'};
fetch(url,{
method:'POST',
body:JSON.stringify(data),
headers:{
'Content-Type':'application/json'
},
keepalive:true// 尝试在页面卸载后继续发送请求
});
}
然而,
pagehide
、
visibilitychange
、
unload
、
beforeunload
事件都存在可靠性问题。数据显示,即使多个事件一起使用,大约有 10% 的数据没有被发送就消失了。
妙用 fetchLater()
fetchLater()
的功能正如其名:它要求浏览器在未来某个时刻确保发送请求,即使页面已经关闭或用户导航到其他页面。
fetchLater()
的语法如下:
const fetchLaterResult =fetchLater(request, options);
fetchLater()
接受两个参数,与 fetch() 的参数相同:
request
:可以是一个字符串形式的 URL,或者是一个 Request 实例。
options
:可选项,它扩展了
fetch()
中的
options
,并增加了一个名为
activateAfter
的超时设置。
fetchLater()
返回一个
FetchLaterResult
对象,它目前只包含一个只读属性
activated
。当指定的「稍后」时间点到来且请求已经发出时,
activated
属性会被设置为
true
。需要注意的是,对于
fetchLater()
发出的请求,其任何响应都不会被保留。
request
在使用时,最简单的形式是直接传入一个 URL 作为请求:
fetchLater('/endpoint/');
并且,
fetchLater()
继承了
fetch()
的灵活性,允许用户为其请求设置多种选项。这些选项包括自定义头部信息、控制凭据的处理方式、指定 POST 请求体,以及利用
AbortController
在必要时取消请求。
fetchLater('/endpoint/',{
method:'GET',
cache:'no-store',
mode:'same-origin',
headers:{Authorization:'SUPER_SECRET'},
});
options
fetchLater()
的
options
参数扩展了
fetch()
的选项,新增了
activateAfter
超时设置,使得请求能够在设定的超时时间后或页面卸载时(两者中较早发生者)自动触发。
例如,如果有一个应用,用户通常会在整个工作日中保持开启状态。在这种情况下,您可以设置一个一小时的超时时间,以确保在分析数据时拥有更精细的粒度,同时确保即使用户在这一小时内任何时候退出应用,也能够成功发送数据。随后,您可以为下一个小时的分析数据设置新的
fetchLater()
请求,以确保数据的持续收集和发送。
const hourInMilliseconds =60*60*1000;
fetchLater('/endpoint/',{activateAfter: hourInMilliseconds});
尝试 fetchLater()
目前,
fetchLater()
仍处于实验状态,现在可以在
chrome://flags/#enable-experimental-web-platform-features
中启用
Experimental Web Platform
功能标志来启用
fetchLater()
API。