当您向网络服务器发出请求时,可能会发生故障。这可能是因为用户已断开连接,或者远程服务器已关闭。
虽然本文档主要侧重于介绍如何处理 Service Worker 中的 GET
请求,但您也可以使用其他方法,例如 POST
、PUT
或 DELETE
。这些方法通常用于与后端 API 通信,为 Web 应用提供数据。如果这些请求在没有 Service Worker 而失败时,它们必须由用户在重新在线后手动重试 - 用户可能并不总是记得要做的事。
如果它描述的是您的应用,并且混合使用了 Service Worker,则理想情况下,您需要在用户恢复在线状态时重新尝试发送失败的请求。BackgroundSync API 提供了解决此问题的方法。当 Service Worker 检测到失败的网络请求时,可以进行注册,以便在浏览器检测到已返回连接时接收 sync
事件。即使用户已经离开注册它的页面,系统也可能会传递 sync
事件,因此,相比其他重试失败请求的方法,该事件更有效。
Workbox 使用 workbox-background-sync
模块抽象化此 API,这使得 BackgroundSync API 更易于与其他 Workbox 模块一起使用。它还为尚不支持 BackgroundSync 的浏览器实施后备策略。
基本用法
BackgroundSyncPlugin
从 workbox-background-sync
模块中导出,可用于将失败的请求加入队列,并在未来的 sync
事件触发时重试这些请求:
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 24 * 60 // Retry for max of 24 Hours (specified in minutes)
});
registerRoute(
/\/api\/.*\/*.json/,
new NetworkOnly({
plugins: [bgSyncPlugin]
}),
// An optional third parameter specifies the request method
'POST'
);
此处,BackgroundSyncPlugin
应用于将 POST 请求与检索 JSON 数据的 API 路由匹配的路由。如果用户处于离线状态,BackgroundSyncPlugin
会在用户重新联网后重试请求,但最多只会持续一天的时间。
高级用法
workbox-background-sync
还提供了 Queue
类,您可以实例化该类并向其中添加失败的请求。与 BackgroundSyncPlugin
一样,失败的请求会存储在 IndexedDB 中,并在浏览器认为连接恢复时尝试。
创建队列
如需创建队列,请使用表示队列名称的字符串实例化 Queue
对象:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
队列名称用作标记名称的一部分,该标记名称由全局 SyncManager
提供的 register()
方法创建。它也是用于 IndexedDB 数据库提供的对象存储的名称。
将请求添加到队列中
创建 Queue
实例后,您可以使用其 pushRequest()
方法向其添加失败的请求:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
self.addEventListener('fetch', (event) => {
// Add in your own criteria here to return early if this
// isn't a request that should use background sync.
if (event.request.method !== 'POST') {
return;
}
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone());
return response;
} catch (error) {
await queue.pushRequest({request: event.request});
return error;
}
};
event.respondWith(bgSyncLogic());
});
添加到队列后,请求会在 Service Worker 收到 sync
事件时自动重试,因为浏览器认为网络再次可用。不支持 BackgroundSync API 的浏览器每次启动 Service Worker 时都会重试请求,这是一种重试失败请求的有效方式,但是一种回退方式。
测试 workbox-background-sync
测试后台同步行为可能会比较棘手,但可在 Chrome 开发者工具中完成。目前的最佳方法是如下所示:
- 加载用于注册 Service Worker 的页面。
- 关闭计算机的网络连接或网络服务器。请勿使用 Chrome 开发者工具中的离线切换开关!离线复选框仅影响来自页面的请求,但 Service Worker 请求将继续进行。
- 发出应使用
workbox-background-sync
加入队列的网络请求。您可以通过查看Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
来检查已加入队列的请求。 - 现在,您需要恢复网络连接或重新开启网络服务器。
- 前往
Chrome DevTools > Application > Service Workers
,强制提前sync
事件。输入workbox-background-sync:<your queue name>
的标记名称,其中<your queue name>
是您设置的队列的名称。 - 点击“同步”按钮。
- 您现在应该会看到之前失败的网络请求重试并完成。因此,IndexedDB 存储区应该为空,因为请求已成功重放。
总结
使用 workbox-background-sync
重试失败的网络请求是提升用户体验和提升应用可靠性的好方法,例如允许用户重新提交失败的 API 请求,以免丢失想要发送到 API 的数据。它还可以用来填补您自己的数据缺口,例如分析。事实上,workbox-google-analytics
模块在后台使用 workbox-background-sync
来重试失败的请求,以便向 Google Analytics 发送数据。
无论您的使用情形是什么,workbox-background-sync
都能简化此类任务,为您提升开发者体验并为您提供更多机会来提升 Web 应用的用户体验和功能。