Service Workers:浏览器什么时候再次同步回来?
Service Workers: when does the browser sync back again?
我正在使用 Google Workbox 构建一个渐进式 Web 应用程序。我已经使用 bgSync(在我的构建文件夹中)设置了一个服务工作者,以便我的 POST 请求被推送到队列并在用户重新获得连接时发送到我的端点,但是同步事件到底什么时候发生?
出于开发目的,我使用 Chrome 中包含的 "Sync" 按钮,详见此答案:,但这是手动的,我希望请求是应用程序恢复在线后立即发送到端点,但是当我连接时我的请求没有发送,我必须手动单击 "Sync" 按钮才能发生,它确实工作得很好,但用户赢了在真实场景中单击“同步”按钮。
准确地说,我想知道在我的 service-worker 中是否有办法检测应用程序何时恢复在线并强制同步。或者知道同步何时发生。这是一个供参考的片段(使用 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 中的请求。我们需要使用 Workbox 队列 class 而不是插件。
// 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/React/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 按钮强制我的 service worker 运行 queue.replayRequests(),所以后台同步功能不会自动发生,我必须手动点击按钮让它发生。
您可以通过利用以分钟为值的 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
我正在使用 Google Workbox 构建一个渐进式 Web 应用程序。我已经使用 bgSync(在我的构建文件夹中)设置了一个服务工作者,以便我的 POST 请求被推送到队列并在用户重新获得连接时发送到我的端点,但是同步事件到底什么时候发生?
出于开发目的,我使用 Chrome 中包含的 "Sync" 按钮,详见此答案:
准确地说,我想知道在我的 service-worker 中是否有办法检测应用程序何时恢复在线并强制同步。或者知道同步何时发生。这是一个供参考的片段(使用 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 中的请求。我们需要使用 Workbox 队列 class 而不是插件。
// 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/React/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 按钮强制我的 service worker 运行 queue.replayRequests(),所以后台同步功能不会自动发生,我必须手动点击按钮让它发生。
您可以通过利用以分钟为值的 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