服务人员:浏览器何时重新同步回?

时间:2018-12-14 20:18:41

标签: service-worker progressive-web-apps workbox background-sync

我正在使用Google Workbox构建一个渐进式Web应用程序。我已经在bgSync中建立了一个服务工作者(在我的构建文件夹中),以便在用户重新建立连接时将我的POST请求推送到队列中并发送到我的终结点,但是同步事件何时准确发生?

出于开发目的,我使用Chrome随附的“同步”按钮,具体说明如下:How to manually trigger a background sync (for testing)?,但这是手动操作,我希望将请求尽快发送到端点。应用程序重新联机,但是当我建立连接时,我的请求没有发送,我必须手动单击“同步”按钮以使其发生,并且确实可以正常工作,但用户不会真正单击“同步”按钮。场景。

准确地说,我想知道在我的服务人员内部是否有一种方法可以检测应用程序何时重新联机并强制进行同步。或知道何时同步。以下是供参考的代码段(使用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'
);

2 个答案:

答案 0 :(得分:4)

因此,从今天开始,Chrome中的后台同步尝试将已排队的请求推送3次(从未在工作箱或后台同步文档中说明):

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

如果用户在15分钟后没有连接,则这些请求只会卡在indexedDB内,直到新的排队请求尝试推送其余请求为止。在我们期望用户几个小时没有互联网连接的情况下,这不是很有用。

有计划(自2016年开始!)实施PeriodicSync,这将使开发人员可以选择浏览器尝试进行同步的次数和时间,但是从未真正实施过,请参见:{{3 }}

尽管我提出了一个笨拙的解决方案,可能不是最好的解决方案,但它可以满足我的需要。有一个同步事件,我们可以操作该事件以重试已卡在indexedDB中的请求。不过,我们需要使用Workbox Queue类而不是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 / 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按钮,该按钮强制我的服务工作者运行queue.replayRequests(),因此后台同步功能不会自动发生,因此必须手动单击一个按钮才能使它发生。

答案 1 :(得分:0)

您可以利用以分钟为单位的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