我有一个问题,我MessageChannel
没有从服务人员向客户发送消息。为什么 MessageChannel 永远阻塞而客户端永远不会收到消息?
在 sw onfetch
事件中我创建了一个MessageChannel
然后我做postMessage
,但是客户端永远不会被addEventListener('message'
解雇,为什么?
对于服务人员,我创建了这样的方法:
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);
});
}
在客户端上,我希望在这里收到消息:
// 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);
});
但我从来没有在客户端收到消息,如果没有超时,它将永远保持 w8。
更新
我试过的:
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);
});
}
我得到的唯一日志是:
导航到http://localhost:3000/ navigator.serviceWorker.ready
ServiceWorker 注册成功,范围: