push イベント

ここまでで、ユーザーの登録とプッシュ メッセージの送信について説明しました。次のステップでは、このプッシュ メッセージをユーザーのデバイスで受信し、通知を表示します(その他の必要な処理も行います)。

プッシュ イベント

メッセージが受信されると、Service Worker でプッシュ イベントが送信されます。

プッシュ イベント リスナーを設定するコードは、JavaScript で記述する他のイベント リスナーとかなり似ています。

self.addEventListener('push', function(event) {
    if (event.data) {
    console.log('This push event has data: ', event.data.text());
    } else {
    console.log('This push event has no data.');
    }
});

Service Worker を初めて使用するデベロッパーにとって、このコードで最も奇妙なのは self 変数です。self は、Service Worker であるウェブ ワーカーでよく使用されます。self はグローバル スコープを指します(ウェブページの window など)。一方、ウェブ ワーカーと Service Worker の場合、self はワーカー自体を指します。

上記の例では、self.addEventListener() は、イベント リスナーを Service Worker 自体に追加するものと考えることができます。

プッシュ イベントの例では、データがあるかどうかを確認し、コンソールに出力します。

push イベントからデータを解析する方法は他にもあります。

// Returns string
event.data.text()

// Parses data as JSON string and returns an Object
event.data.json()

// Returns blob of data
event.data.blob()

// Returns an arrayBuffer
event.data.arrayBuffer()

ほとんどのユーザーは、アプリケーションに期待する内容に応じて json() または text() を使用します。

この例では、プッシュイベント リスナーを追加する方法とデータにアクセスする方法を示していますが、2 つの非常に重要な機能が欠落しています。通知が表示されておらず、event.waitUntil() も使用されていません。

待機時間

Service Worker について理解しておくべきことの 1 つは、Service Worker コードが実行されるタイミングを制御できないことです。ブラウザを復帰させるタイミングと終了するタイミングはブラウザが決定します。「重要な処理で忙しい」とブラウザに伝える唯一の方法は、event.waitUntil() メソッドにプロミスを渡すことです。これにより、渡された Promise が解決されるまで、ブラウザは Service Worker の実行を継続します。

プッシュ イベントの場合、渡された Promise が解決する前に通知を表示する必要があるという追加要件があります。

通知を表示する基本的な例を次に示します。

self.addEventListener('push', function(event) {
    const promiseChain = self.registration.showNotification('Hello, World.');

    event.waitUntil(promiseChain);
});

self.registration.showNotification() を呼び出すと、ユーザーに通知を表示し、通知が表示された後に解決される Promise を返します。

この例をできるだけわかりやすくするために、このプロミスを promiseChain という変数に割り当てています。その後、これは event.waitUntil() に渡されます。冗長なコードであることは承知しておりますが、waitUntil() に渡すべきものを誤解したり、Promise チェーンが破損したりしたことが原因で、さまざまな問題が発生しています。

データのネットワーク リクエストとアナリティクスによる push イベントのトラッキングの複雑な例は、次のようになります。

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        return self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

ここでは、Promise pushReceivedTracking() を返す関数を呼び出しています。この関数は、例として、アナリティクス プロバイダにネットワーク リクエストを送信するふりをします。また、ネットワーク リクエストを作成してレスポンスを取得し、通知のタイトルとメッセージのレスポンス データを使用して通知を表示します。

これらのプロミスを Promise.all() と組み合わせることで、これらのタスクの両方が実行されている間、サービス ワーカーが存続するようにできます。結果の Promise は event.waitUntil() に渡されます。つまり、ブラウザは両方の Promise が完了するまで待機してから、通知が表示されたことを確認し、Service Worker を終了します。

waitUntil() とその使用方法に注意する必要がある理由は、デベロッパーが直面する最も一般的な問題の 1 つとして、Promise チェーンが正しくないか破損している場合に、Chrome にこの「デフォルト」通知が表示されることです。

Chrome のデフォルト通知の画像

Chrome では、プッシュ メッセージが受信され、event.waitUntil() に渡されたプロミスが完了した後に、サービス ワーカーのプッシュ イベントで通知が表示されない場合にのみ、「このサイトはバックグラウンドで更新されました」という通知が表示されます。

デベロッパーがこれにとらわれる主な理由は、コードが self.registration.showNotification() を呼び出すことが多いものの、返された Promise を使用して何もしないためです。これにより、デフォルトの通知が断続的に表示されます。たとえば、上記の例で self.registration.showNotification() の戻り値を削除すると、この通知が表示される可能性があります。

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

見落としがちであることがわかります。

この通知が表示された場合は、Promise チェーンと event.waitUntil() を確認してください。

次のセクションでは、通知のスタイル設定と表示できるコンテンツについて説明します。

次のステップ

Codelab