18

ページに ServiceWorker を登録していて、そこにデータを渡して、IndexedDB に保存し、後でネットワーク リクエストに使用できるようにしたいと考えています (これはアクセス トークンです)。

ネットワーク リクエストを使用し、フェッチを使用して SW 側でそれらをキャッチするのが正しいことですか、それとももっと賢い方法がありますか?

私と同様のことを疑問に思っている将来の読者への注意:

SW 登録オブジェクトのプロパティを設定します。たとえば、self.registration.foo を Service Worker 内の関数に設定し、ページで次の操作を行います。

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

結果はTypeError: reg.foo is not a function. これはServiceWorkerのライフサイクルと関係があると思います。つまり、それを変更することはできず、将来的にそれらの変更にアクセスできると予想されるため、SWとのインターフェースはすべてpostMessageスタイルでなければならない可能性が高いため、おそらくフェッチを使用するだけです一番いい方法は…?

4

2 に答える 2

30

そのため、(ライフサイクルの問題により) アプリから SW 内のメソッドを実際に呼び出すことができないことが判明したため、postMessage API を使用してシリアライズされた JSON メッセージを渡す必要があります (コールバックなどを渡さないようにします)。

次のアプリ コードを使用して、制御 SW にメッセージを送信できます。

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

SW コードで以下と組み合わせます。

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

SWのコンソールで次の結果になります。

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'});
于 2015-02-14T08:28:14.857 に答える