I have a problem where my MessageChannel does not send a message from a service worker to a client. Why MessageChannel blocks forever and the client never gets message?

In the sw on fetch event I create a MessageChannel then I do postMessage , however the client never gets addEventListener('message' fired why ?

For service worker I created method like that:

self.addEventListener("fetch", async (event) => { // Exit early if we don't have access to the client. // Eg, if it's cross-origin. if (!event.clientId) return null; // eslint-disable-next-line const client = await clients.get(event.clientId); const response = await sendMessageToClient(client, { url: event.request.url }, 5000); }) async function sendMessageToClient(client, message, timeoutAfter) { // Exit early if we don't get the client. // Eg, if it closed. if (!client) return null; // This wraps the message posting/response in a promise, which will resolve if the response doesn't // contain an error, and reject with the error if it does. return await new Promise((resolve, reject) => { const messageChannel = new MessageChannel(); messageChannel.port1.onmessage = function (event) { if (event.data && event.data.error) { reject(event.data.error); } else { resolve(event.data); } }; // This sends the message data as well as transferring messageChannel.port2 to the client. // The client can then use the transferred port to reply via postMessage(), which // will in turn trigger the onmessage handler on messageChannel.port1. // See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage client.postMessage(message, [messageChannel.port2]); // Set up the timeout setTimeout(() => { messageChannel.port1.close(); messageChannel.port2.close(); reject('Promise timed out after ' + timeoutAfter + ' ms'); }, timeoutAfter); }); }

On the client I expect to get message here:

// Set up a listener for messages posted from the service worker. // The service worker is set to post a message to specific client only // so you should see this message event fire once. // You can force it to fire again by visiting this page in an Incognito window. navigator.serviceWorker.addEventListener('message', function (event) { console.log(event.data); });

But I never get the message on client and if there is no time out it will w8 forever.

Update

what i have tried:

window.addEventListener('message', function (event) { console.log('window.addEventListener', event.data) }); window.onmessage = function (event) { console.log('window.onmessage', event.data) }; navigator.serviceWorker.addEventListener('message', function (event) { console.log('navigator.serviceWorker.addEventListener', event.data) }); navigator.serviceWorker.onmessage = function (event) { console.log('navigator.serviceWorker.onmessage', event.data) }; // navigator.serviceWorker.controller.addEventListener('message', function (event) { console.log('navigator.serviceWorker.contoller.addEventListener', event.data) }); // navigator.serviceWorker.controller.onmessage = function (event) { console.log('navigator.serviceWorker.contoller.onmessage', event.data) }; navigator.serviceWorker.ready.then(function (registration) { console.log('navigator.serviceWorker.ready'); registration.active.addEventListener('message', function (event) { console.log('registration.active.addEventListener', event.data) }); registration.active.onmessage = function (event) { console.log('registration.active.onmessage', event.data) }; }); navigator.serviceWorker.register("sw.js") .then(function (registration) { // Registration was successful console.log("ServiceWorker registration successful with scope: ", registration.scope); }) .catch(function (error) { console.error("Service Worker Error", error); }); }

and the only logs I got were: