【问题标题】:How do I call a method on my ServiceWorker from within my page?如何从我的页面中调用我的 ServiceWorker 上的方法?
【发布时间】:2015-02-14 08:10:57
【问题描述】:

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

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

未来读者的注意事项与我相似:

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

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

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

【问题讨论】:

    标签: progressive-web-apps service-worker function-call


    【解决方案1】:

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

    您可以使用以下应用代码向控制软件发送消息:

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

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

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

    这会在我的软件控制台中产生以下结果:

    postMessage received Object {hello: "world"}
    

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

    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 中通过它进行响应:

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

    【讨论】:

    • 有一个全面的演示展示了如何定义触发不同message处理程序行为的不同“命令”:github.com/GoogleChrome/samples/tree/gh-pages/service-worker/…
    • 如果您需要向您的控制 ServiceWorker 发送消息并获得某种响应,发出 http 请求通常是最简单的方法。您的 ServiceWorker 将在其 fetch 事件中看到这一点,并且可以使用 JSON 或您想要的任何内容进行回复。
    【解决方案2】:

    要将数据传递给您的 Service Worker,上述方法是一个好方法。但万一,如果有人仍然难以实现它,那么还有其他方法可以解决这个问题,

    1 - 在加载 service-worker 时附加数据以获取参数(例如,来自 sw.js -> sw.js?a=x&b=y&c=z

    2- 现在在 service worker 中,使用 self.self.location.search 获取这些数据。

    注意,只有当您传递的数据对于特定客户端不经常更改时,这才是有益的,否则它将不断更改该特定客户端的服务工作者的加载 URL,并且每次客户端重新加载时或重新访问,安装新的 Service Worker。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多