javascript - Service Worker 收不到消息

标签 javascript service-worker progressive-web-apps

注意:使用 Create-React-App 模板...(修改其中的 Service Worker)

我正在使用通信 channel api 向服务 worker 发送消息以进行缓存。我使用 xmlhttp 请求是因为它的进度 api 因为 fetch 需要一个不确定的加载程序 afaik。

因此,在收到 readystate 4 和状态代码 200 上的数据后,我转到 postMessage 到 SW。我在客户端登录,但在服务 worker 中没有收到消息。

我正在本地开发并使用 Chrome 扩展来允许本地测试 SW 和构建: https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en

客户端片段

xhr.onreadystatechange = function(){
    if (this.readyState == 4 && this.status == 200) {
        const res = JSON.parse(this.responseText);

        function sendMessage(msg){
            console.log("SEND SW MESSAGE");
            const msgChan = new MessageChannel();
            // 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. If you'd prefer, it's possible to call
            // controller.postMessage() and set up the onmessage handler independently of a promise, but this is
            // a convenient wrapper.
            return new Promise(function(resolve, reject){
                console.log("Promise Scope");

                msgChan.port1.onmessage = function(event){
                    event.data.error ? reject(event.data.error) : resolve(event.data);
                }
                // This sends the message data as well as transferring messageChannel.port2 to the service worker.
                // The service worker 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
                navigator.serviceWorker.controller.postMessage(msg, [msgChan.port2]);
            });
        }

        sendMessage(res).then(function(){
            console.log("SW MESSAGE SENT");
            // Storing Quake Data
            that.props.setQuakes(res[0]);
            // Storing Three Data Obj - SSR Parsing and Creation
            that.props.setThreeData(res[1]);   
            // Greenlight 
            that.props.setVizInitSuccess(true);
        }).catch(function(err){
            console.log("Error Caching Data: "+err);
        });
    } };

服务人员片段

function registerValidSW(swUrl, config) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      // Set up a listener for messages posted from the service worker.
      // The service worker is set to post a message to all its clients once it's run its activation
      // handler and taken control of the page, 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.onmessage = function(event) {
        console.log("SERVICE WORKER RECIEVED MESSAGE");
        console.log(event);

        event.ports[0].postMessage("SW Says Hello Back!");
        if (event.data.requireData == true && 'caches' in window) {
          // Check for cache'd data and load
          // clients.matchAll().then(clients => {
          //     clients.forEach(client => {
          //         console.log(client);
          //         //send_message_to_client(client, msg).then(m => console.log("SW Received Message: "+m));
          //     })
          // })

          // caches.open('threeData').then(function(cache){
          //   console.log("SW Cache");
          //   console.log(cache)
          //   event.ports[0].postMessage(cache);  
          // });

        } else {
          // Cache Data
          caches.open('threeData').then(function(cache){
            cache.put('/data.json', new Response(event.data.json))
          });
        }
      };
...

最佳答案

Service Worker 文件中使用的

navigatorWorkerNavigator 接口(interface),而不是 Navigator 接口(interface)。

WorkerNavigatorNavigator 接口(interface)的一个子集,允许从 Worker (在本例中为 Service worker) 访问。 WorkerNavigator Reference .

因此服务 worker 文件中的 navigator 不包含 serviceWorker 对象。因此当您调用 navigator.serviceWorker.onMessage 时它会抛出错误。

要从客户端接收消息,请使用Service Worker 文件 中的self.addEventListener

self.addEventListener('message', event => {
  console.log(`[Message] event: `, event.data);
});

关于javascript - Service Worker 收不到消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57193534/

相关文章:

angular - Safari 中的服务 worker

javascript - 我应该如何更新 Service Worker 和缓存的 PWA 文件

android - gcm 推送通知,渐进式 webapp

javascript - 增加鼠标悬停时文本的大小 css/jquery/html

javascript - 如何在 Firebase 函数中以编程方式定期触发基于计时器的方法?

javascript - 在 Microsoft Edge 上注册服务工作人员时出错

javascript - serviceWorker 'activate' 和 'message' 事件未触发

javascript - 调整对象大小时的 Fabric.js 线条渲染

javascript - 获取与 lodash 匹配模式的字符串结尾

angularjs - PWA 被添加到主屏幕后丢失了它的参数和查询参数