我在我的页面上注册了一个ServiceWorker,并希望将一些数据传递给它,以便它可以存储在IndexedDB中,以后用于网络请求(它是一个访问令牌).
使用网络请求并使用fetch在SW端捕获它们是正确的,还是有更聪明的东西?
请注意未来的读者对我有类似的想法:
在SW注册对象上设置属性,例如将self.registration.foo设置为服务工作者中的函数,并在页面中执行以下操作:
navigator.serviceWorker.getRegistration().then(function(reg) { reg.foo; })
Run Code Online (Sandbox Code Playgroud)
'TypeError:reg.foo不是函数'的结果.我认为这与ServiceWorker的生命周期有关,这意味着你无法修改它并期望将来可以访问这些修改,因此任何具有SW的接口都可能必须是postMessage样式,所以也许只使用fetch是最好的方式去......?
owe*_*ncm 20
所以事实证明你实际上无法从你的应用程序中调用SW中的方法(由于生命周期问题),所以你必须使用postMessage API来传递序列化的JSON消息(所以没有传递回调等).
您可以使用以下应用代码向控制SW发送消息:
navigator.serviceWorker.controller.postMessage({'hello': 'world'})
Run Code Online (Sandbox Code Playgroud)
结合SW代码中的以下内容:
self.addEventListener('message', function (evt) {
console.log('postMessage received', evt.data);
})
Run Code Online (Sandbox Code Playgroud)
这导致我的SW控制台中出现以下内容:
postMessage received Object {hello: "world"}
Run Code Online (Sandbox Code Playgroud)
因此,通过传入一个消息(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]);
Run Code Online (Sandbox Code Playgroud)
然后您可以在消息处理程序中的Service Worker中通过它进行响应:
evt.ports[0].postMessage({'hello': 'world'});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5606 次 |
| 最近记录: |