何を今さらって感じですが・・。
ぱっと思い出せなくて調べたので、忘れないようにメモっとく。
Browser → ServiceWorker
これは割と簡単で、`navigator.serviceWorker.controller`に生えてる`postMessage()`を使えばいい。
// Browser (async function main() { // もちろん前もって登録しておいて await navigator.serviceWorker.register('./sw.js'); const ctrl = navigator.serviceWorker.controller; ctrl.postMessage({ type: 'data', payload: { x: 1 }}); }());
こうやって送って、受け取り側はこう。
// ServiceWorker self.addEventListener('message', ev => { const { type, payload } = ev.data; console.log(type, payload); });
そしてふと思う、逆はどうやるんや・・?
ServiceWorker → Browser
ここに正解があった。
samples/service-worker/post-message at gh-pages · GoogleChrome/samples · GitHub
`MessageChannel`を使ってやり取りする。
あえてServiceWorker側に状態を定義して、簡単なカウンターを作ってみる例。
// Browser (async function main() { await navigator.serviceWorker.register('./sw.js'); const { $incBtn, $decBtn, $span } = initView(); const ctrl = navigator.serviceWorker.controller; const { port1, port2 } = new MessageChannel(); // handle messages from service worker // addEventListener() does not work...? port1.onmessage = ev => { $span.textContent = ev.data; }; // init service worker with `MessagePort` ctrl.postMessage({ type: 'init' }, [ port2 ]); // now, we can interact with service worker! $incBtn.onclick = () => ctrl.postMessage({ type: '++' }); $decBtn.onclick = () => ctrl.postMessage({ type: '--' }); }());
最初に`MessagePort`の片側を渡しておくのがキモ。
`Worker#postMessage()`は、第2引数で`Transferable`なものを渡せる。
最初は`port1`と`port2`の意味がわからんかったけど、互いに一方交の通信ができるから2つ必要ってこと。
// ServiceWorker let port; let count = 0; self.addEventListener('message', ev => { const { type } = ev.data; switch (type) { case 'init'