У меня есть простой сервисный работник, который на 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
зарегистрирован после сообщение размещены работником сервиса. Тем не менее прослушиватель событий все еще получает сообщение.
![enter image description here](https://i.stack.imgur.com/auNZz.png)
Я подозреваю, что это потому, что сообщения планируются асинхронно:
postMessage () планирует отправку MessageEvent только после завершения всех ожидающих контекстов выполнения. Например, если postMessage () вызывается в обработчике событий, этот обработчик событий будет выполняться до завершения, как и все остальные обработчики для того же события, до отправки MessageEvent.
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Notes
Однако я не уверен, что это означает в этом конкретном c примере. Например, когда обработчик события fetch завершился, гарантированно ли работал клиент JavaScript, и, следовательно, прослушиватель события сообщения будет зарегистрирован?
У меня есть приложение большего размера, которое выполняет нечто подобное к вышесказанному, но клиент JavaScript запускается чуть позже при загрузке страницы, поэтому я хотел бы знать, когда именно должен быть зарегистрирован прослушиватель событий, чтобы избежать условий гонки и гарантировать, что сообщение, отправленное работником службы, будет получил.