How do I call a method on my ServiceWorker from within my page?

后端 未结 2 645
没有蜡笔的小新
没有蜡笔的小新 2021-02-01 23:55

I have a ServiceWorker registered on my page and want to pass some data to it so it can be stored in an IndexedDB and used later for network requests (it\'s an access token).

2条回答
  •  不要未来只要你来
    2021-02-02 00:45

    So it turns out that you can't actually call a method within a SW from your app (due to lifecycle issues), so you have to use a postMessage API to pass serialized JSON messages around (so no passing callbacks etc).

    You can send a message to the controlling SW with the following app code:

    navigator.serviceWorker.controller.postMessage({'hello': 'world'})
    

    Combined with the following in the SW code:

    self.addEventListener('message', function (evt) {
      console.log('postMessage received', evt.data);
    })
    

    Which results in the following in my SW's console:

    postMessage received Object {hello: "world"}
    

    So by passing in a message (JS object) which indicates the function and arguments I want to call my event listener can receive it and call the right function in the SW. To return a result to the app code you will need to also pass a port of a MessageChannel in to the SW and then respond via postMessage, for example in the app you'd create and send over a MessageChannel with the data:

    var messageChannel = new MessageChannel();
    messageChannel.port1.onmessage = function(event) {
      console.log(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(message, [messageChannel.port2]);
    

    and then you can respond via it in your Service Worker within the message handler:

    evt.ports[0].postMessage({'hello': 'world'});
    

提交回复
热议问题