push イベント

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

push イベント

メッセージを受信すると、Service Worker で push イベントがディスパッチされます。

push イベント リスナーを設定するコードは、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 である Web Worker でよく使用されます。self は、ウェブページの window のようなグローバル スコープを指します。ただし、ウェブワーカーと Service Worker の場合、self はワーカー自体を指します。

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

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

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() を使用します。

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

待機時間

Service Worker について理解すべきことの一つは、Service Worker コードを実行するタイミングをほとんど制御できないことです。スリープから復帰するタイミングと終了するタイミングはブラウザが決定します。「重要な作業で忙しいんだ」とブラウザに伝えるには、event.waitUntil() メソッドに Promise を渡す必要があります。これにより、ブラウザは、渡された Promise が解決するまで Service Worker を実行したままにします。

プッシュ イベントには、渡された Promise が解決される前に通知を表示するという要件がもう 1 つあります。

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

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

    event.waitUntil(promiseChain);
});

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

この例をできる限りわかりやすくするために、この 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 を Promise.all() と組み合わせることで、両方のタスクが実行されている間、Service Worker を確実に停止できます。結果の Promise は event.waitUntil() に渡されます。つまり、ブラウザは両方の Promise が完了するまで待機してから、通知が表示されていることを確認し、Service Worker を終了します。

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

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

Chrome では、「このサイトはバックグラウンドで更新されています」という通知のみが表示されます。プッシュ メッセージを受信すると、event.waitUntil() に渡された Promise が終了すると Service Worker のプッシュ イベントに通知は表示されません

デベロッパーがこれに遭遇する主な理由は、コードが 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