客户端页面和 service worker 之间的双向通信

Bi-directional communication between a client page and a service worker

有一个由 preact-cli(使用 workbox)生成的 preact 应用程序,我的 objective 是在 service worker 上注册一个 'message' 事件处理程序,post 来自应用程序并最终收到回复。

类似于:

/* app.js */
navigator.serviceWorker.postMessage('marco');

const response = ? // get the response somehow
/* sw.js */
addEventListener('message', function (e) { return 'polo' });

我对 service worker 没有太多经验,有很多移动部分让我感到困惑,比如 workbox 在 service worker 上施展魔法,预先隐藏注册 sercice worker 的代码和 service worker 很棘手一般调试。

到目前为止,我已经按照这里的 preact-cli 文档的指示在 src/ 目录中放置了一个 sw.js 文件:https://preactjs.com/cli/service-worker/

我知道我应该附加一个事件侦听器,但我找不到关于要附加哪个对象的文档。

(Workbox 和 Preact 都与这个问题没有太大关系。Workbox 允许您在服务工作线程中使用您喜欢的任何其他代码,Preact 也应该适用于您的客户端应用程序。)

This example page demonstrates sending a message from a client page to a service worker and then responding, using MessageChannel。客户端页面上使用的相关帮助程序代码如下所示:

function sendMessage(message) {
  return new Promise(function(resolve, reject) {
    const messageChannel = new MessageChannel();
    messageChannel.port1.onmessage = function(event) {
      // The response from the service worker is in event.data
      if (event.data.error) {
        reject(event.data.error);
      } else {
        resolve(event.data);
      }
    };

    navigator.serviceWorker.controller.postMessage(message,
      [messageChannel.port2]);
  });
}

然后在你的 service worker 中,你使用了 MessageChannel 的端口来响应:

self.addEventListener('message', function(event) {
  // Your code here.

  event.ports[0].postMessage({
    error: // Set error if you want to indicate a failure.
    message: // This will show up as event.data.message.
  });
});

您也可以使用 Comlink library 来简化逻辑。