Memperkenalkan Pengambilan Latar Belakang

Jake Archibald
Jake Archibald

Pada tahun 2015 kami memperkenalkan Sinkronisasi Latar Belakang yang memungkinkan pekerja layanan untuk menunda pekerjaan hingga pengguna memiliki konektivitas. Ini berarti pengguna bisa mengetik pesan, tekan kirim, dan tinggalkan situs bahwa pesan akan dikirim sekarang atau saat mereka memiliki konektivitas.

Ini adalah fitur yang berguna, tetapi mengharuskan pekerja layanan hidup selama durasi pengambilan. Itu bukan masalah untuk pekerjaan singkat seperti mengirim pesan, tetapi jika tugas itu terlalu lama browser akan mematikan pekerja layanan, jika tidak, ini merupakan risiko bagi privasi pengguna dan daya baterai.

Jadi, bagaimana jika Anda perlu mengunduh sesuatu yang mungkin memakan waktu lama, seperti film, podcast, atau level game. Itulah kegunaan Background Fetch.

Pengambilan Latar Belakang tersedia secara default sejak Chrome 74.

Berikut ini demo singkat dua menit yang menunjukkan status biasanya, vs menggunakan Pengambilan Latar Belakang:

Coba demo sendiri lalu jelajahi kodenya.

Cara kerjanya

Pengambilan latar belakang berfungsi seperti ini:

  1. Anda memberi tahu browser untuk melakukan sekelompok pengambilan di latar belakang.
  2. Browser mengambil hal-hal tersebut, menampilkan progres kepada pengguna.
  3. Setelah pengambilan selesai atau gagal, browser akan membuka pekerja layanan Anda dan mengaktifkan peristiwa untuk memberi tahu Anda apa yang terjadi. Di sinilah Anda memutuskan apa yang akan dilakukan dengan respons, jika ada.

Jika pengguna menutup halaman ke situs Anda setelah langkah 1, tidak apa-apa, download akan dilanjutkan. Karena pengambilan sangat terlihat dan mudah dibatalkan, tidak ada masalah privasi yang terlalu panjang tugas sinkronisasi latar belakang. Karena pekerja layanan tidak terus-menerus berjalan, jangan khawatir bahwa itu dapat menyalahgunakan sistem, seperti menambang bitcoin di latar belakang.

Pada beberapa platform (seperti Android) browser dapat ditutup setelah langkah 1, karena browser dapat menyerahkan pengambilan ke sistem operasi.

Jika pengguna memulai download saat offline, atau offline selama download, latar belakang pengambilan akan dijeda dan dilanjutkan nanti.

API

Deteksi fitur

Seperti fitur baru lainnya, Anda perlu mendeteksi apakah browser mendukungnya. Untuk Pengambilan Latar Belakang, sesederhana:

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

Memulai pengambilan latar belakang

API utama menghentikan pendaftaran service worker, jadi pastikan Anda telah mendaftarkan pekerja layanan terlebih dahulu. Lalu:

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 menggunakan tiga argumen:

Parameter
id string
secara unik mengidentifikasi pengambilan latar belakang ini.

backgroundFetch.fetch akan menolak jika ID cocok dengan latar belakang yang sudah ada pengambilan.

requests Array<Request|string>
Item yang akan diambil. {i>String<i} akan diperlakukan sebagai URL, dan diubah menjadi Request melalui new Request(theString).

Anda dapat mengambil sesuatu dari asal lain selama sumber daya memungkinkannya melalui CORS.

Catatan: Saat ini Chrome tidak mendukung permintaan yang akan memerlukan preflight CORS.

options Objek yang mungkin mencakup hal berikut:
options.title string
Judul untuk ditampilkan browser beserta progresnya.
options.icons Array<IconDefinition>
Array objek dengan `src`, `size`, dan `type`.
options.downloadTotal number
Ukuran total isi respons (setelah diekstrak).

Meskipun bersifat opsional, sebaiknya Anda menyediakannya. Ini digunakan untuk memberitahukan pengguna seberapa besar download, dan untuk memberikan informasi kemajuan. Jika Anda tidak memberikan ini, browser akan memberi tahu pengguna bahwa ukurannya tidak diketahui, dan akibatnya pengguna mungkin lebih dapat membatalkan download.

Jika download pengambilan di latar belakang melebihi jumlah yang diberikan di sini, download akan dibatalkan. Penting tidak masalah jika ukuran download lebih kecil dari downloadTotal, jadi jika Anda tidak yakin berapa total unduhannya, sebaiknya Anda memilih untuk tetap berhati-hati.

backgroundFetch.fetch menampilkan promise yang di-resolve dengan BackgroundFetchRegistration. Saya akan membahasnya secara detail nanti. Promise akan ditolak jika pengguna memilih untuk tidak ikut mendownload, atau satu parameter yang diberikan tidak valid.

Menyediakan banyak permintaan untuk satu pengambilan di latar belakang memungkinkan Anda menggabungkan hal-hal yang secara logis satu hal kepada pengguna. Misalnya, sebuah film dapat dibagi menjadi ribuan sumber daya (biasanya MPEG-DASH), dan dilengkapi dengan sumber daya tambahan seperti gambar. Satu level game dapat tersebar di banyak Referensi JavaScript, gambar, dan audio. Namun, bagi pengguna, ini hanyalah "film", atau "level".

Mendapatkan pengambilan latar belakang yang ada

Anda dapat memperoleh pengambilan latar belakang yang ada seperti ini:

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

...dengan meneruskan id pengambilan latar belakang yang Anda inginkan. get menampilkan undefined jika tidak ada pengambilan di latar belakang aktif dengan ID tersebut.

Pengambilan di latar belakang dianggap "aktif" sejak didaftarkan, hingga berhasil, gagal, atau dibatalkan.

Anda dapat memperoleh daftar semua pengambilan di latar belakang yang aktif menggunakan getIds:

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

Pendaftaran pengambilan latar belakang

BackgroundFetchRegistration (bgFetch dalam contoh di atas) memiliki hal berikut:

Properti
id string
ID pengambilan latar belakang.
uploadTotal number
Jumlah byte yang akan dikirim ke server.
uploaded number
Jumlah byte yang berhasil dikirim.
downloadTotal number
Nilai yang diberikan saat pengambilan di latar belakang didaftarkan, atau nol.
downloaded number
Jumlah byte yang berhasil diterima.

Nilai ini dapat menurun. Misalnya, jika koneksi terputus dan download tidak dapat dilanjutkan, dalam hal ini browser memulai ulang pengambilan resource tersebut dari awal.

result

Salah satu dari berikut ini:

  • "" - Pengambilan di latar belakang aktif, sehingga belum ada hasil.
  • "success" - Pengambilan di latar belakang berhasil.
  • "failure" - Pengambilan latar belakang gagal. Nilai ini hanya muncul saat pengambilan di latar belakang gagal sepenuhnya, karena browser tidak dapat mencoba lagi/melanjutkan.
failureReason

Salah satu dari berikut ini:

  • "" - Pengambilan di latar belakang belum gagal.
  • "aborted" – Pengambilan di latar belakang dibatalkan oleh pengguna, atau abort() dipanggil.
  • "bad-status" - Salah satu respons memiliki status tidak baik, mis. 404.
  • "fetch-error" - Salah satu pengambilan gagal karena alasan lain, misalnya CORS, MIX, respons parsial yang tidak valid, atau kegagalan jaringan umum untuk pengambilan yang tidak dapat dicoba lagi.
  • "quota-exceeded" - Kuota penyimpanan tercapai selama di latar belakang pengambilan.
  • "download-total-exceeded" - `downloadTotal` yang diberikan sebelumnya terlampaui.
recordsAvailable boolean
Apakah permintaan/respons yang mendasarinya dapat diakses?

Jika nilainya salah, match dan matchAll tidak dapat digunakan.

Metode
abort() Menampilkan Promise<boolean>
Batalkan pengambilan latar belakang.

Promise yang ditampilkan akan di-resolve dengan true (benar) jika pengambilan berhasil dibatalkan.

matchAll(request, opts) Menampilkan Promise<Array<BackgroundFetchRecord>>
Dapatkan permintaan beserta responsnya.

Argumen di sini sama dengan cache Google Cloud Platform. Memanggil tanpa argumen akan menampilkan promise untuk semua kumpulan data.

Lihat di bawah untuk detail selengkapnya.

match(request, opts) Menampilkan Promise<BackgroundFetchRecord>
Seperti di atas, tetapi diselesaikan dengan kecocokan pertama.
Acara
progress Diaktifkan saat salah satu dari uploaded, downloaded, result, atau Perubahan failureReason.

Memantau progres

Hal ini dapat dilakukan melalui peristiwa progress. Ingat bahwa downloadTotal adalah nilai berapa pun yang Anda diberikan, atau 0 jika Anda tidak memberikan nilai.

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}%`);
});

Mendapatkan permintaan dan respons

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);
});

record adalah BackgroundFetchRecord, dan terlihat seperti ini:

Properti
request Request
Permintaan yang diberikan.
responseReady Promise<Response>
Respons yang diambil.

Respons berada di balik promise karena mungkin belum diterima. Janji akan menolak jika pengambilan gagal.

Peristiwa pekerja layanan

Acara
backgroundfetchsuccess Semuanya berhasil diambil.
backgroundfetchfailure Satu atau beberapa pengambilan gagal.
backgroundfetchabort Satu atau beberapa pengambilan gagal.

Fungsi ini hanya berguna jika Anda ingin melakukan pembersihan data terkait.

backgroundfetchclick Pengguna mengklik UI progres download.

Objek peristiwa memiliki hal berikut:

Properti
registration BackgroundFetchRegistration
Metode
updateUI({ title, icons }) Memungkinkan Anda mengubah judul/ikon yang awalnya Anda tetapkan. Ini opsional, tetapi memungkinkan Anda memberikan lebih banyak konteks jika diperlukan. Anda hanya dapat melakukannya *sekali* selama Peristiwa backgroundfetchsuccess dan backgroundfetchfailure.

Bereaksi terhadap keberhasilan/kegagalan

Kita telah melihat peristiwa progress, tetapi itu hanya berguna saat pengguna memiliki halaman yang terbuka untuk di situs Anda. Manfaat utama pengambilan di latar belakang adalah segala sesuatunya akan terus berfungsi setelah pengguna meninggalkan halaman, atau bahkan menutup browser.

Jika pengambilan di latar belakang berhasil diselesaikan, pekerja layanan Anda akan menerima Peristiwa backgroundfetchsuccess, dan event.registration akan menjadi pendaftaran pengambilan latar belakang.

Setelah peristiwa ini, permintaan dan respons yang diambil tidak lagi dapat diakses, sehingga jika Anda ingin menyimpannya, pindahkan ke tempat lain seperti API cache.

Seperti kebanyakan peristiwa pekerja layanan, gunakan event.waitUntil agar pekerja layanan tahu kapan peristiwa terjadi sudah lengkap.

Misalnya, dalam pekerja layanan Anda:

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!' });
  }());
});

Kegagalan mungkin disebabkan oleh satu 404, yang mungkin tidak penting bagi Anda, menyalin beberapa respons ke dalam {i>cache<i} seperti di atas.

Bereaksi terhadap klik

UI yang menampilkan progres download dan hasilnya dapat diklik. Peristiwa backgroundfetchclick di pekerja layanan memungkinkan Anda bereaksi terhadap ini. Seperti di atas, event.registration akan menjadi latar belakang pendaftaran pengambilan.

Hal yang umum dilakukan dengan peristiwa ini adalah membuka jendela:

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

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

Referensi lainnya

Koreksi: Versi sebelumnya dari artikel ini salah menyebut Pengambilan Latar Belakang sebagai "standar web". API ini saat ini tidak berada di jalur standar, spesifikasinya dapat ditemukan di WICG sebagai Draf Laporan Grup Komunitas.