服务人员:浏览器什么时候重新同步



我正在使用Google Workbox构建一个渐进式web应用程序。我已经用bgSync(在我的构建文件夹中(设置了一个服务工作者,这样当用户重新获得连接时,我的POST请求就会被推送到队列并发送到我的端点,但同步事件到底是什么时候发生的?

出于开发目的,我使用Chrome中包含的"同步"按钮,如下所述:如何手动触发后台同步(用于测试(?,但这是手动的,我希望在应用程序恢复在线后立即将请求发送到端点,但当我获得连接时,我的请求不会被发送,我必须手动单击"同步"按钮才能实现,它确实很好地工作,但用户在实际情况下不会单击"同步按钮"。

确切地说,我想知道在我的服务人员内部是否有一种方法可以检测应用程序何时恢复在线,并强制同步。或者知道同步何时发生。以下是一个供参考的片段(使用Workbox 3.0.0(:

const bgSyncPlugin = new workbox.backgroundSync.Plugin('myQueue', {
callbacks: {
requestWillEnqueue: (storableRequest) => {}, // I show a push notification indicating user is offline
requestWillReplay: (storableRequest) => {},
queueDidReplay: (storableRequestArray) => {} // If I get a response, I show a push notification
}
},
);
workbox.routing.registerRoute(
"https://myapi.com/action",
workbox.strategies.networkOnly({
plugins: [bgSyncPlugin]
}),
'POST'
);

因此,截至今天,Chrome中的后台同步尝试推送排队的请求3次(工作簿或后台同步文档中从未解释过(:

  • 第一次:当实际第一次尝试请求时,浏览器意识到用户没有连接,因此将请求放入indexedDB中
  • 第二次:第一次尝试后正好5分钟
  • 第三次:在第一次尝试后整整15分钟

如果用户在15分钟后没有连接,那么请求就会被困在indexedDB中,直到一个新的排队请求试图推送其余请求。在我们预计用户数小时内没有互联网连接的情况下,这不是很有帮助。

有计划(自2016年以来!(实现PeriodicSync,这将让开发人员选择浏览器尝试同步的次数和时间,但它从未真正实现,请参阅:https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/periodicSync

不过,我想出了一个笨拙的解决方案,可能不是最好的,但它满足了我的需求。有一个同步事件,我们可以操作它来重试我们在indexedDB中卡住的请求。不过,我们需要使用WorkboxQueue类而不是Plugin。

// our service worker file
// we create a push notification function so the user knows when the requests are being synced
const notificate = (title, message) => {
self.registration.showNotification(title, {
body: message,
icon: '/image.png',
tag: 'service-worker'
})
}
// let's create our queue
const queue = new workbox.backgroundSync.Queue('myQueue', {
callbacks: {
requestWillEnqueue: () => {
notificate('You are offline! 🛠', 'Your request has been submitted to the Offline 
queue. The queue will sync with the server once you are back online.')
}
});
// sync event handler
self.addEventListener("sync", (ev) => {
queue.replayRequests().then((a) => {
notificate('Syncing Application... 💾', 'Any pending requests will be sent to the 
server.');
}).catch(
notificate('We could not submit your requests. ❌', 'Please hit the 'Sync Pending 
Requests' button when you regain internet connection.')
);
});

现在,在我们的HTML/Rect/Node视图文件中,我们可以执行以下操作:

// this will trigger our Sync event
<button type="button" onClick={navigator.serviceWorker.ready.then(reg =>
reg.sync.register('myEvent'))}>{'Sync Pending
Requests'}</button>

请注意,我创建了一个html按钮,它强制我的服务工作者运行queue.readRequests((,因此后台同步功能不会自动发生,我必须手动单击一个按钮才能发生。

您可以通过利用以分钟为值的maxRetentionTime参数来更改重试时间。例如,如果您想重试2天,您可以像这样初始化队列:

const queue = new workbox.backgroundSync.Queue('requestsQueue', {
maxRetentionTime: 48 * 60 //2 days
});

当然,若队列中的请求将被成功执行,它将不再重试运行。

文档中的更多信息:https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.backgroundSync.Queue

最新更新