【发布时间】: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