大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
Background Fetch简称bgFetch。
1.为什么是Background Fetch?
深入理解浏览器Background Fetch。 Created by Decipher Zone Softwares
1.1 为什么要Background Fetch?
当 Web 应用程序需要下载大文件时,例如电影、音频文件和软件,通常可能会出现问题,因为用户需要保持与页面的连接才能完成下载。 如失去连接,关闭选项卡等任务将停止。
为什么要Background Fetch?From:istockphoto
Background Synchronization 为 service workers 提供了一种延迟处理直到用户连接的方法。但是不能用于长时间运行的任务,例如下载大文件。 同时,要求 service worker 在完成之前保持活动状态,因为为了节省电池寿命、防止在后台发生不需要的任务,浏览器将在某个时候终止任务。
1.2 Background Fetch解决了什么痛点?
Background Fetch API 解决了这个问题。 它为 Web 开发人员创建了一种方式,让浏览器在后台执行一些操作,例如,当用户单击按钮下载视频文件时。 然后浏览器以用户可见的方式执行提取,显示进度、提供取消下载的方法。 下载完成后,浏览器会打开 Service Worker,此时应用程序可以根据需要对响应执行某些操作。
如果用户在离线时启动进程,后台提取 API 将启用提取。 一旦连接起来,它就会开始。 如果用户下线,该过程将暂停,直到用户再次上线。
2.Background Fetch如何工作?
Background Fetch工作流程如下:
- 告诉浏览器在后台执行一组fetch。
- 浏览器调用fetch,向用户显示进度。
- 一旦获取完成或失败,浏览器就会打开service workers并触发一个事件来告诉你发生了什么,由开发者决定如何处理响应。
如果用户在第 1 步后关闭了站点的页面,下载将继续。
fetch是高度可见的并且很容易中止,所以不存在太长的后台同步任务的隐私问题。 而且service worker 也不会持续运行,所以不用担心滥用系统,例如在后台挖矿。
在某些平台(例如 Android)上,浏览器可能会在第 1 步后关闭,因为浏览器可以将fetch操作交给操作系统。如果用户在离线时开始下载,或者在下载过程中离线,后台fetch将暂停并稍后恢复。
3.浏览器兼容
3.1 特征检测
与任何新功能一样,需要检测浏览器是否支持它。 对于 Background Fetch,可以通过如下代码快速检测:
if ('BackgroundFetchManager' in self) {
//浏览器支持Background Fetch!
}
从caniuse的数据来看,该API的浏览器整体支持率达到了73.58%。Chrome从74版本开始,Edge从79版本开始都已经支持Background Fetch。不过,可惜的是,FireFox和Safari目前支持并不好。
3.2 实例化Background Fetch
使用 Background Fetch 需要注册一个 service worker。 然后调用 backgroundFetch.fetch() 来执行,同时返回一个Promise。
Background Fetch提取可能会请求多个文件。 在下面的示例中,请求了 MP3 和 JPEG。
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.fetch(
// service worker的fetch方法
"my-fetch",
["/ep-5.mp3", "ep-5-artwork.jpg"],
// 请求MP3和JPEG
{
title: "Episode 5: Interesting things.",
icons: [
{
sizes: "300x300",
src: "/ep-5-icon.png",
type: "image/png",
},
],
downloadTotal: 60 * 1024 * 1024,
}
);
});
3.3 获取已有的Background Fetch
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
通过传递Background Fetch的id来获取, 如果没有使用该 ID 的Background Fetch,则返回 undefined。
Background Fetch从它被注册的那一刻起就被认为是“活跃的”,直到它成功、失败或被终止。可以使用 getIds 获取所有活动Background Fetch的列表:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
3.4 跟踪Background Fetch进度
可以通过进度事件来完成。请记住,downloadTotal可以是任何值,未提供,则为 0。
bgFetch.addEventListener('progress', () => {
// If we didn't provide a total, we can't provide a %.
if (!bgFetch.downloadTotal) return;
const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
console.log(`Download progress: ${percent}%`);
});
3.5 获取请求和响应
bgFetch.match('/ep-5.mp3').then(async (record) => {
if (!record) {
console.log('No record found');
return;
}
console.log(`Here's the request`, record.request);
const response = await record.responseReady;
console.log(`And here's the response`, response);
});
在 Chrome 当前的实现中,您只能在 backgroundfetchsuccess、backgroundfetchfailure 和 backgroundfetchabort service worker 事件期间获取请求和响应(见下文)
4.本文总结
本文主要和大家介绍浏览器的新特性Background Fetch,因为Background Fetch本身的复杂性,文章没有过多的展开。但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。
参考资料
https://developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API
https://caniuse.com/?search=Background%20Fetch
https://developer.chrome.com/blog/background-fetch/