当您向网络服务器发出请求时,可能会失败。这可能是因为用户连接中断,或者远程服务器已宕机。
虽然本文档主要侧重于处理 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
应用于与检索 JSON 数据的 API 路由的 POST 请求路由匹配。如果用户处于离线状态,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 应用的用户体验和功能。