【问题标题】:Timing of `postMessage` inside service worker `fetch` event handlerService Worker `fetch` 事件处理程序中`postMessage` 的计时
【发布时间】:2020-02-09 15:08:22
【问题描述】:

我有一个简单的服务人员,它在fetch 上向客户端发布一条消息:

// main.js

navigator.serviceWorker.register("./service-worker.js");

console.log("client: addEventListener message");
navigator.serviceWorker.addEventListener("message", event => {
  console.log("client: message received", event.data);
});
<script src="main.js"></script>
// service-worker.js

self.addEventListener("fetch", event => {
  console.log("service worker: fetch event");

  event.waitUntil(
    (async () => {
      const clientId =
        event.resultingClientId !== ""
          ? event.resultingClientId
          : event.clientId;
      const client = await self.clients.get(clientId);

      console.log("service worker: postMessage");
      client.postMessage("test");
    })()
  );
});

当我查看控制台日志时,很明显message 事件侦听器是在服务人员发布消息之后注册的。尽管如此,事件监听器仍然会收到消息。

我怀疑这是因为消息是异步调度的:

postMessage() 安排 MessageEvent 仅在所有挂起的执行上下文完成后才被调度。例如,如果在事件处理程序中调用 postMessage(),则在调度 MessageEvent 之前,该事件处理程序将运行到完成,同一事件的任何剩余处理程序也将运行。

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Notes

但是,我不确定这在这个特定示例中意味着什么。例如,当 fetch 事件处理程序运行完成时,是否保证客户端 JavaScript 已运行,因此将注册消息事件侦听器?

我有一个更大的应用程序正在执行与上述类似的操作,但客户端 JavaScript 在页面加载时稍晚运行,因此我想知道必须在何时注册事件侦听器以避免竞争条件并保证service worker发布的消息会被接收到。

【问题讨论】:

    标签: dom service-worker postmessage


    【解决方案1】:

    默认情况下,从页面的控制服务工作者发送到页面的所有消息(使用 Client.postMessage())在页面加载时排队,并在页面的 HTML 文档被加载和解析后(即在DOMContentLoaded 事件触发)。可以通过调用 ServiceWorkerContainer.startMessages() 更早地开始分派这些消息,例如,如果您在页面完成加载之前使用 EventTarget.addEventListener() 调用了消息处理程序,但想立即开始处理消息。

    https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/startMessages

    【讨论】:

    • 感谢您的研究。这是使用后台工作者的一个非常关键的点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多