Service Worker を使用して通知を管理する

Kate Jeffreys
Kate Jeffreys

この Codelab では、サービス ワーカーを使用して通知を管理します。この手順では、サービス ワーカーと、通知権限のリクエストと通知の送信の基本をすでに理解していることを前提としています。通知について復習する必要がある場合は、Notifications API スタートガイドの Codelab をご覧ください。Service Worker の詳細については、Matt Gaunt 氏の Service Worker の概要をご覧ください。

サンプルアプリと開始用コードを理解する

まず、新しい Chrome タブでライブアプリを確認します。

  1. `Ctrl+Shift+J`(Mac の場合は `Command+Option+J`)を押して、デベロッパー ツールを開きます。
  2. [コンソール] タブをクリックします。

  3. [フィルタ] ボックスの横にある [レベル] プルダウンで [情報] オプションが選択されていることを確認します。

  4. 公開中のアプリの DevTools コンソールに、次のコンソール メッセージが表示されます。

    TODO: Implement getRegistration()

    これは、この Codelab で実装する関数スタブからのメッセージです。

それでは、サンプルアプリのコードを見てみましょう。

  1. public/index.js をご覧ください。

    • 実装する関数には、registerServiceWorkergetRegistrationunRegisterServiceWorkersendNotification の 4 つのスタブがあります。

    • requestPermission 関数は、通知を送信するユーザーの権限をリクエストします。Notifications API の codelab を始めるを完了している場合は、ここで requestPermission 関数が使用されていることに気づくでしょう。唯一の違いは、権限リクエストの解決後にユーザー インターフェースも更新するようになったことです。

    • updateUI 関数は、アプリのすべてのボタンとメッセージを更新します。

    • initializePage 関数は、ブラウザのサービス ワーカー機能の機能検出を実行し、アプリのユーザー インターフェースを更新します。

    • スクリプトは、ページが読み込まれるまで待ってから初期化します。

  2. public/service-worker.js を開きます。

    名前のとおり、このファイルをサービス ワーカーとして登録するコードをアプリに追加します。

    このファイルはアプリではまだ使用されていませんが、サービス ワーカーがアクティブになったときにコンソールにメッセージを出力する開始コードが含まれています。

    public/service-worker.js にコードを追加して、サービス ワーカーが通知を受け取ったときに処理するようにします。

Service Worker を登録する

このステップでは、ユーザーがアプリの UI で [Register service worker] をクリックしたときに実行されるコードを記述します。このコードは、public/service-worker.js をサービス ワーカーとして登録します。

  1. public/index.js を開きます。registerServiceWorker 関数を次のコードに置き換えます。

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    registerServiceWorkerasync function 宣言を使用して、プロミスの処理をより便利にしています。これにより、Promise の解決された値を await できます。たとえば、上記の関数は、UI を更新する前にサービス ワーカーの登録結果を待機します。詳しくは、MDN の await をご覧ください。

  2. ユーザーがサービス ワーカーを登録できるようになったので、サービス ワーカー登録オブジェクトへの参照を取得できます。public/index.js で、getRegistration 関数を次のコードに置き換えます。

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    上記の関数は、Service Worker API を使用して、現在の Service Worker 登録(存在する場合)を取得します。サービス ワーカー登録への参照を少し便利に取得できます。

  • サービス ワーカーの登録機能を完成させるには、サービス ワーカーの登録を解除するコードを追加します。unRegisterServiceWorker 関数を次のコードに置き換えます。

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

ライブアプリを表示しているタブで、ページを再読み込みします。[Service Worker を登録] ボタンと [Service Worker の登録を解除] ボタンが機能するようになります。

Service Worker に通知を送信する

このステップでは、ユーザーがアプリの UI で [通知を送信] をクリックしたときに実行されるコードを記述します。このコードは、通知を作成し、サービス ワーカーが登録されていることを確認してから、postMessage メソッドを使用してサービス ワーカーに通知を送信します。

public/index.js を開き、sendNotification 関数を次のコードに置き換えます。

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

このコードは次のように動作します。

  • sendNotification は非同期関数であるため、await を使用してサービス ワーカー登録への参照を取得できます。

  • サービス ワーカーの postMessage メソッドは、アプリからサービス ワーカーにデータを送信します。詳しくは、postMessage に関する MDN ドキュメントをご覧ください。

  • このコードは、postMessage 関数にアクセスする前に navigator.serviceWorker.controller プロパティの存在を確認します。アクティブなサービス ワーカーがない場合、またはページが強制的に更新された場合(Shift+再読み込み)、navigator.serviceWorker.controllernull になります。詳しくは、MDN の ServiceWorker コントローラに関するドキュメントをご覧ください。

Service Worker で通知を処理する

このステップでは、サービス ワーカーに投稿されたメッセージを処理し、ユーザーに通知を表示するコードを記述します。

public/service-worker.js を開きます。ファイルの末尾に次のコードを追加します。

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

簡単に説明します。

  • self はサービス ワーカー自体への参照です。

  • サービス ワーカーが通知の表示を処理するようになりましたが、メインアプリの UI は引き続きユーザーから通知の権限を取得する役割を担っています。権限が付与されていない場合、showNotification から返された Promise は拒否されます。上記のコードでは、catch ブロックを使用して、キャッチされない Promise 拒否エラーを回避し、このエラーをより適切に処理しています。

このシリーズの次の Codelab であるプッシュ通知サーバーを構築するに進みます。