如何从页面内调用 ServiceWorker 上的方法? [英] How do I call a method on my ServiceWorker from within my page?

查看:56
本文介绍了如何从页面内调用 ServiceWorker 上的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的页面上注册了一个 ServiceWorker,并希望将一些数据传递给它,以便它可以存储在 IndexedDB 中,并在以后用于网络请求(它是一个访问令牌).

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).

仅使用网络请求并使用 fetch 在 SW 端捕获它们是正确的做法,还是有更聪明的做法?

Is the correct thing just to use network requests and catch them on the SW side using fetch, or is there something more clever?

给想知道与我类似问题的未来读者的注意事项:

在软件注册对象上设置属性,例如将 self.registration.foo 设置为 service worker 中的函数并在页面中执行以下操作:

Setting properties on the SW registration object, e.g. setting self.registration.foo to a function within the service worker and doing the following in the page:

navigator.serviceWorker.getRegistration().then(function(reg) { reg.foo; })

结果 TypeError: reg.foo is not a function.我认为这与 ServiceWorker 的生命周期有关,这意味着您无法修改它并期望将来可以访问这些修改,因此任何带有 SW 的接口都可能必须是 postMessage 样式,所以也许只使用 fetch 是最好的方法是......?

Results in TypeError: reg.foo is not a function. I presume this is something to do with the lifecycle of a ServiceWorker meaning you can't modify it and expect those modification to be accessible in the future, so any interface with a SW likely has to be postMessage style, so perhaps just using fetch is the best way to go...?

推荐答案

所以事实证明你实际上不能从你的应用程序中调用 SW 中的方法(由于生命周期问题),所以你必须使用 postMessage用于传递序列化 JSON 消息的 API(因此不会传递回调等).

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'})

结合SW代码中的以下内容:

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"}

因此,通过传入一条消息(JS 对象),该消息指示我想调用我的事件侦听器的函数和参数,可以接收它并在 SW 中调用正确的函数.要将结果返回给应用程序代码,您还需要将 MessageChannel 的端口传递给 SW,然后通过 postMessage 进行响应,例如在您创建的应用程序中,并通过 MessageChannel 发送数据:

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]);

然后您可以在消息处理程序中的 Service Worker 中通过它进行响应:

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

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

这篇关于如何从页面内调用 ServiceWorker 上的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆