【问题标题】:Service Workers: when does the browser sync back again?Service Worker:浏览器何时再次同步?
【发布时间】:2018-12-14 20:18:40
【问题描述】:

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

出于开发目的,我使用 Chrome 中包含的“同步”按钮,详见此答案:How to manually trigger a background sync (for testing)?,但这是手动操作,我希望在应用程序启动后立即将请求发送到端点重新联机,但是当我获得连接时,我的请求没有发送,我必须手动单击“同步”按钮才能发生这种情况,它确实工作得很好,但用户不会在真实场景中单击“同步”按钮。

确切地说,我想知道在我的 service-worker 内部是否有办法检测应用程序何时重新联机并强制同步。或者知道同步发生的时间。这是一个 sn-p 供参考(使用 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'
);

【问题讨论】:

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


    【解决方案1】:

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

    • 第一次:第一次实际尝试请求时,浏览器发现用户没有连接,所以将请求放入indexedDB中。
    • 第二次:在第一次尝试后 5 分钟。
    • 第三次:第一次尝试后正好 15 分钟。

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

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

    虽然我想出了一个笨拙的解决方案,可能不是最好的解决方案,但它可以满足我的需要。有一个同步事件,我们可以操纵它来重试我们停留在 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 按钮,它强制我的 service worker 运行 queue.replayRequests(),因此后台同步功能不会自动发生,我必须手动单击一个按钮才能发生。

    【讨论】:

      【解决方案2】:

      您可以通过利用以分钟为值的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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-11-03
        • 1970-01-01
        • 2017-12-02
        • 2018-06-11
        • 2019-12-03
        • 1970-01-01
        • 2018-12-29
        • 1970-01-01
        相关资源
        最近更新 更多