バックグラウンド取得の概要

2015 年に Google はバックグラウンド同期を導入し、 ユーザーが接続できるまで作業を延期します。つまり、ユーザーは メッセージを送ってから、[送信] を押し、メッセージが今すぐまたは 接続します。

これは便利な機能ですが、サービス期間中に Service Worker を 取得しますメッセージの送信のような短い作業では問題になりませんが、タスクに あまりに長くなると、ブラウザが Service Worker を強制終了します。そうしないと、ユーザーのプライバシーが損なわれ、 できます。

では、ダウンロードに時間がかかる映画、ポッドキャスト、 制限します。そのために、バックグラウンド フェッチを使用します。

バックグラウンド フェッチは、Chrome 74 以降でデフォルトで使用できます。

こちらは 2 分間の簡単なデモで、従来の状態とバックグラウンド フェッチを使用した場合を比較したものです。

ご自身でデモを試しコードを参照します。

仕組み

バックグラウンド取得は次のように動作します。

  1. 一連のフェッチをバックグラウンドで実行するようブラウザに指示します。
  2. ブラウザはこれらを取得して、進行状況をユーザーに表示します。
  3. 取得が完了または失敗すると、ブラウザは Service Worker を開き、イベントを発生させます。 何が起きたかを教えてくれます。ここで、回答の処理方法を決定します。

ステップ 1 の後にユーザーがサイトのページを閉じても問題ありません。ダウンロードは続行されます。なぜなら、 取得がはっきりと表示され、簡単に中止できる。長すぎるというプライバシーに関する懸念はない バックグラウンド同期タスクを実行しますService Worker は常に動作しているわけではないため、 バックグラウンドでビットコインのマイニングを行うなどして、システムを悪用する可能性があると判断しました。

一部のプラットフォーム(Android など)では、ステップ 1 の後でブラウザが閉じることがあります。これは、 ブラウザは取得をオペレーティング システムに引き渡せます。

ユーザーがオフライン中にダウンロードを開始したり、ダウンロード中にオフラインになった場合、バックグラウンド 取得は一時停止され、後で再開されます。

API

機能検出

他の新機能と同様に、ブラウザがこの機能をサポートしているかどうかを検出する必要があります。バックグラウンド フェッチについては、 次のようにシンプルにできます。

if ('BackgroundFetchManager' in self) {
  // This browser supports Background Fetch!
}

バックグラウンド取得の開始

メイン API が Service Worker の登録を終了し、 必ず Service Worker を登録してください以下の手順を行います。

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
    title: 'Episode 5: Interesting things.',
    icons: [{
      sizes: '300x300',
      src: '/ep-5-icon.png',
      type: 'image/png',
    }],
    downloadTotal: 60 * 1024 * 1024,
  });
});

backgroundFetch.fetch は次の 3 つの引数を取ります。

パラメータ
id string
でこのバックグラウンド フェッチを一意に識別します。

ID が既存の背景と一致する場合、backgroundFetch.fetch は拒否されます 取得します

requests Array<Request|string>
取得するアイテム。文字列は URL として扱われ、 new Request(theString) 経由の Request

リソースで許可されている限り、他のオリジンから取得できます。 CORS

注: 現在のところ、Chrome は CORS プリフライトが必要です

options 以下を含むことができるオブジェクト。
options.title string
進行状況とともに表示されるブラウザのタイトル。
options.icons Array<IconDefinition>
`src`、`size`、`type` を持つオブジェクトの配列。
options.downloadTotal number
レスポンス本文の合計サイズ(gzip 圧縮解除後)。

これは省略可能ですが、指定することを強くおすすめします。データ アナリストは、 ダウンロードのサイズ、進行状況に関する情報などがあります。「新規顧客の獲得」目標を ブラウザはユーザーにサイズが不明であることを通知し、その結果、 ダウンロードを中止する可能性があります。

バックグラウンドでの取得によるダウンロード回数がここで指定した数を超えると、ダウンロードは中止されます。です。 ダウンロードが downloadTotal より小さい場合はまったく問題ありません。したがって、 ダウンロードの合計数がどの程度になるかを把握しておくことが重要です。

backgroundFetch.fetch は、BackgroundFetchRegistration で解決される Promise を返します。私は 後ほど詳しく説明します。ユーザーがダウンロードをオプトアウトしている場合、またはいずれか 1 つの場合、Promise は拒否されます。 無効なパラメータです。

1 回のバックグラウンド フェッチで多数のリクエストを提供することで、論理的には ユーザーに提示しますたとえば、映画が数千個のリソース(通常、 MPEG-DASH), 画像などの追加リソースが付属していますあるゲームのレベルは、 JavaScript、画像、音声の各リソース。ユーザーにとっては「映画」または「レベル」だけです。

既存のバックグラウンド取得を取得する

既存のバックグラウンド取得は次のように取得できます。

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});

必要なバックグラウンド フェッチの id を渡します。見つからない場合、getundefined を返します。 バックグラウンド取得がアクティブになります

バックグラウンド フェッチは「アクティブ」と見なされる登録から成功するまで 失敗するか中止されます

getIds を使用すると、すべてのアクティブなバックグラウンド フェッチのリストを取得できます。

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});

バックグラウンド フェッチの登録

BackgroundFetchRegistration(上記の例では bgFetch)は次のようになります。

プロパティ
id string
バックグラウンド フェッチ用の ID。
uploadTotal number
サーバーに送信されるバイト数。
uploaded number
正常に送信されたバイト数。
downloadTotal number
バックグラウンド フェッチの登録時に指定された値、または あります。
downloaded number
正常に受信されたバイト数。

この値は減少する可能性があります。たとえば、接続が切断されてダウンロードがうまくいかない場合や、 再開された場合、ブラウザはそのリソースの取得をゼロから再開します。

result

次のいずれかになります。

  • "" - バックグラウンド フェッチがアクティブなため、結果はまだありません。
  • "success" - バックグラウンドの取得が成功しました。
  • "failure" - バックグラウンドの取得に失敗しました。この値は、 ブラウザでの再試行/再開ができないため、バックグラウンド フェッチは完全に失敗します。
failureReason

次のいずれかになります。

  • "" - バックグラウンドの取得は失敗していません。
  • "aborted" – バックグラウンド フェッチがユーザーによって中止された。または abort() が呼び出されました。
  • "bad-status" - レスポンスの 1 つが not-ok ステータスでした。例:404。
  • "fetch-error" - 他のなんらかの理由で取得が失敗しました(例: CORS、MIX、無効な部分的レスポンス、またはフェッチでの一般的なネットワーク障害など、 再試行はできません。
  • "quota-exceeded" - バックグラウンドで保存容量の上限に達しました 取得します
  • "download-total-exceeded" - 指定された「downloadTotal」は 超えています。
recordsAvailable boolean
基になるリクエスト/レスポンスにアクセスできるか。

これが false の場合、match になり、matchAll は使用できません。

メソッド
abort() Promise<boolean> を返します。
バックグラウンド フェッチを中止します。

フェッチが正常に中止された場合、返される Promise は true で解決されます。

matchAll(request, opts) 戻り値Promise<Array<BackgroundFetchRecord>>
リクエストを取得する 学習します。

ここでの引数は、 キャッシュ API。引数なしで呼び出すと、すべてのレコードに対する Promise が返されます。

詳しくは以下をご覧ください。

match(request, opts) Promise<BackgroundFetchRecord> を返します。
上記と同じですが、次で解決されます 一致します。
イベント
progress uploadeddownloadedresult、または 乗り継ぎ: failureReason 回。

進捗状況の追跡

これを行うには、progress イベントを使用します。downloadTotal は、使用する値が任意の値であることに 値を指定しなかった場合は 0 を返します。

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;

  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});

リクエストとレスポンスの取得

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});

recordBackgroundFetchRecord で、次のようになります。

プロパティ
request Request
提供されたリクエスト。
responseReady Promise<Response>
取得したレスポンス。

レスポンスがまだ受信されていない可能性があるため、Promise の背後になっています。約束 取得が失敗すると拒否されます。

Service Worker イベント

イベント
backgroundfetchsuccess すべてが正常に取得されました。
backgroundfetchfailure 1 つ以上の取得に失敗しました。
backgroundfetchabort 1 つ以上の取得に失敗しました。

これは、関連データをクリーンアップする場合にのみ有用です。

backgroundfetchclick ユーザーがダウンロード進行状況 UI をクリックした。

イベント オブジェクトには次のものがあります。

プロパティ
registration BackgroundFetchRegistration
メソッド
updateUI({ title, icons }) 最初に設定したタイトルやアイコンを変更できます。これは省略可能ですが、 必要に応じて詳細なコンテキストを提供できます。この操作は、 backgroundfetchsuccess イベントと backgroundfetchfailure イベント。

成功/失敗への対応

progress イベントはすでに見てきましたが、これはユーザーがページを開いている場合にのみ有用です。 できます。バックグラウンド取得の主なメリットは、ユーザーがプログラムを終了した後も動作を継続できることです。 ブラウザを閉じることもあります。

バックグラウンド フェッチが正常に完了すると、Service Worker は backgroundfetchsuccess イベント、event.registration はバックグラウンド取得の登録です。

このイベントの後、フェッチ済みのリクエストとレスポンスにはアクセスできなくなります。したがって、 キャッシュ API などの場所に移動してください。

ほとんどの Service Worker イベントと同様に、event.waitUntil を使用して、イベントがいつ発生したかを Service Worker が認識できるようにします。 確認します。

たとえば、Service Worker で次のようにします。

addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Create/open a cache.
    const cache = await caches.open('downloads');
    // Get all the records.
    const records = await bgFetch.matchAll();
    // Copy each request/response across.
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    // Wait for the copying to complete.
    await Promise.all(promises);

    // Update the progress notification.
    event.updateUI({ title: 'Episode 5 ready to listen!' });
  }());
});

失敗の原因は 1 つの 404 にとどまっているかもしれません。404 は重要ではなかったかもしれません。 上記のように、一部のレスポンスをキャッシュにコピーする価値があります。

クリックに反応する

ダウンロードの進行状況と結果を表示している UI がクリック可能になっている。backgroundfetchclick イベント: Service Worker でこれに対応できます。上記のように、event.registration が背景になります フェッチ登録します

このイベントでの一般的な処理は、ウィンドウを開くことです。

addEventListener('backgroundfetchclick', (event) => {
  const bgFetch = event.registration;

  if (bgFetch.result === 'success') {
    clients.openWindow('/latest-podcasts');
  } else {
    clients.openWindow('/download-progress');
  }
});

参考情報

修正: この記事の以前のバージョンでは、バックグラウンド フェッチを「ウェブ標準」と誤って表記していました。この API は現在標準のトラックには存在しません。仕様は WICG でコミュニティ グループ レポートのドラフト版として入手できます。