将成功的 workbox-background-sync 重播传达给打开的客户端

Communicating a successful workbox-background-sync replay to open clients

我正在使用 React 17、Workbox 5 和 react-scripts 4。 我使用 PWA 模板创建了一个 React 应用程序:

npx create-react-app my-app --template cra-template-pwa

我将 workbox-background-sync 中的 BackgroundSyncPlugin 用于我的离线请求,因此当应用再次在线时,请求将自动发送。 问题是我不知道请求何时在我的 React 代码中发送,所以我可以更新一些状态,并向用户显示一条消息。

我如何从 service worker 向我的 React 代码传达请求已发送并且 React 应该更新状态?

提前致谢。

您可以在配置 BackgroundSyncPlugin 时使用自定义 onSync 回调来完成此操作。只要满足重试请求的条件,就会执行此代码而不是 Workbox 的 built-in replayRequests() logic

您可以在此回调中包含您想要的任何逻辑; this.shiftRequest()this.unshiftRequest(entry) 可用于删除排队的请求以便重试它们,如果重试失败则重新添加它们。这是对默认 replayRequests() 的改编,当重试成功时,它将使用 postMessage() 与所有受控 window 客户端通信。

async function postSuccessMessage(response) {
  const clients = await self.clients.matchAll();
  for (const client of clients) {
    // Customize this message format as you see fit.
    client.postMessage({
      type: 'REPLAY_SUCCESS',
      url: response.url,
    });
  }
}

async function customReplay() {
  let entry;
  while ((entry = await this.shiftRequest())) {
    try {
      const response = await fetch(entry.request.clone());
      // Optional: check response.ok and throw if it's false if you
      // want to treat HTTP 4xx and 5xx responses as retriable errors.

      postSuccessMessage(response);
    } catch (error) {
      await this.unshiftRequest(entry);

      // Throwing an error tells the Background Sync API
      // that a retry is needed.
      throw new Error('Replaying failed.');
    }
  }
}

const bgSync = new BackgroundSyncPlugin('api-queue', {
  onSync: customReplay,
});

// Now add bgSync to a Strategy that's associated with
// a route you want to retry:
registerRoute(
  ({url}) => url.pathname === '/api_endpoint',
  new NetworkOnly({plugins: [bgSync]}),
  'POST'
);

在您的客户端页面中,您可以使用 navigator.seviceWorker.addEventListener('message', ...) 来侦听来自 service worker 的传入消息并采取适当的操作。