WEB-API SERVICE-WORKER OFFLINE-FIRST PWA BACKGROUND-PROCESSING DATA-TRANSFER WEB-PERFORMANCE USER-EXPERIENCE MODERN-WEB JAVASCRIPT BROWSER

Background Fetch API: Mengelola Unduhan dan Unggahan Data Skala Besar di Web Secara Tangguh dan Offline

⏱️ 10 menit baca
👨‍💻

Background Fetch API: Mengelola Unduhan dan Unggahan Data Skala Besar di Web Secara Tangguh dan Offline

1. Pendahuluan

Pernahkah Anda frustrasi saat mengunduh file besar atau mengunggah video ke platform web, lalu koneksi internet terputus atau Anda tidak sengaja menutup tab browser? Tiba-tiba, semua progres hilang dan Anda harus memulai dari awal. Ini adalah pengalaman yang menyebalkan dan seringkali menjadi batasan serius bagi aplikasi web modern yang ingin bersaing dengan aplikasi native.

Di sinilah Background Fetch API datang sebagai pahlawan! API ini dirancang khusus untuk mengatasi tantangan transfer data skala besar (unduhan atau unggahan) yang memerlukan ketahanan terhadap gangguan jaringan dan kemampuan untuk berjalan di latar belakang, bahkan ketika pengguna meninggalkan atau menutup halaman web. Bayangkan mengunduh film, podcast, atau mengunggah dataset besar tanpa khawatir progresnya terhenti. Ini adalah game-changer untuk aplikasi offline-first dan Progressive Web Apps (PWA).

Artikel ini akan membawa Anda menyelami Background Fetch API: apa itu, mengapa penting, bagaimana cara kerjanya, dan bagaimana Anda bisa menggunakannya dalam proyek web Anda untuk menciptakan pengalaman pengguna yang jauh lebih tangguh dan efisien. Mari kita mulai!

2. Apa itu Background Fetch API?

Secara sederhana, Background Fetch API memungkinkan aplikasi web untuk mendelegasikan tugas unduhan atau unggahan file besar ke browser, yang kemudian akan menanganinya di latar belakang. Ini mirip dengan bagaimana aplikasi native dapat melanjutkan unduhan meskipun Anda menutupnya.

📌 Poin Penting:

Background Fetch API dibangun di atas Service Worker, yang merupakan fondasi utama untuk kemampuan offline dan background processing di web. Service Worker bertindak sebagai proxy antara aplikasi web dan jaringan, memungkinkan kita mengintersep dan mengelola permintaan jaringan. Background Fetch API memanfaatkan kekuatan ini untuk mengelola siklus hidup transfer data yang kompleks.

Perbedaan dengan Background Sync API: Meskipun sama-sama berjalan di latar belakang, Background Fetch API berbeda dari Background Sync API.

3. Kasus Penggunaan Nyata (Real-world Use Cases)

Background Fetch API membuka banyak kemungkinan untuk meningkatkan pengalaman pengguna di berbagai jenis aplikasi web:

Dengan kemampuan ini, aplikasi web dapat memberikan pengalaman yang jauh lebih andal dan mulus, mendekati fungsionalitas aplikasi native.

4. Memulai dengan Background Fetch API

Untuk menggunakan Background Fetch API, Anda memerlukan Service Worker yang terdaftar. Jika Anda belum memiliki Service Worker, Anda bisa merujuk ke artikel “Service Workers: Senjata Rahasia untuk Aplikasi Web Offline-First dan Super Cepat” untuk panduan memulainya.

Setelah Service Worker Anda aktif, Anda bisa memulai background fetch dari kode JavaScript di halaman web Anda.

4.1. Memulai Permintaan Background Fetch

Untuk memulai background fetch, Anda akan memanggil metode backgroundFetch.fetch() pada objek ServiceWorkerRegistration.

// Di halaman web Anda (main thread)
if ('serviceWorker' in navigator && 'BackgroundFetchManager' in self) {
  navigator.serviceWorker.ready.then(async (registration) => {
    try {
      // ID unik untuk fetch ini
      const fetchId = 'my-large-download-' + Date.now();
      const requests = [
        '/api/large-file-part-1.zip',
        '/api/large-file-part-2.zip',
        // Anda bisa menentukan beberapa URL untuk diunduh secara berurutan atau paralel
      ];
      const options = {
        title: 'Mengunduh Laporan Tahunan',
        icons: [{
          src: '/images/download-icon-128.png',
          sizes: '128x128',
          type: 'image/png'
        }],
        downloadTotal: 1024 * 1024 * 500 // Ukuran total yang diharapkan dalam byte (misal 500MB)
      };

      const bgFetch = await registration.backgroundFetch.fetch(fetchId, requests, options);
      console.log(`Background Fetch '${fetchId}' dimulai.`, bgFetch);

      // Anda bisa mendengarkan event progres di sini juga, tapi lebih baik di Service Worker
      bgFetch.addEventListener('progress', () => {
        const progress = Math.round((bgFetch.downloaded / bgFetch.downloadTotal) * 100);
        console.log(`Progress: ${progress}%`);
        // Update UI Anda di sini
      });

    } catch (error) {
      console.error('Gagal memulai Background Fetch:', error);
    }
  });
} else {
  console.warn('Background Fetch API tidak didukung di browser ini.');
  // Fallback ke metode unduhan tradisional
}

4.2. Menangani Event di Service Worker

Bagian paling krusial adalah bagaimana Service Worker Anda merespons event dari Background Fetch. Ada beberapa event utama:

// Di Service Worker Anda (sw.js)
self.addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;
  console.log(`Background Fetch '${bgFetch.id}' berhasil.`);

  event.waitUntil(async () => {
    // Kumpulkan semua respons dari fetch
    const records = await bgFetch.matchAll();
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      if (response && response.ok) {
        // Lakukan sesuatu dengan data yang berhasil diunduh
        // Misalnya, simpan ke IndexedDB atau Cache Storage
        const blob = await response.blob();
        console.log(`File dari ${record.request.url} (${blob.size} bytes) berhasil diunduh.`);
        // Simpan blob ke IndexedDB atau Cache Storage
        // await caches.open('my-downloads').then(cache => cache.put(record.request, response.clone()));
      }
    });
    await Promise.all(promises);

    // Kirim notifikasi ke user bahwa unduhan selesai
    self.registration.showNotification(`${bgFetch.title} selesai diunduh!`, {
      body: 'File Anda sudah siap untuk diakses secara offline.',
      icon: '/images/download-complete-icon.png'
    });
  });
});

self.addEventListener('backgroundfetchfail', (event) => {
  const bgFetch = event.registration;
  console.error(`Background Fetch '${bgFetch.id}' gagal.`, bgFetch.failureReason);

  // Beri tahu pengguna bahwa unduhan gagal
  self.registration.showNotification(`${bgFetch.title} gagal diunduh!`, {
    body: `Terjadi masalah: ${bgFetch.failureReason}. Silakan coba lagi.`,
    icon: '/images/download-fail-icon.png'
  });
});

self.addEventListener('backgroundfetchabort', (event) => {
  const bgFetch = event.registration;
  console.warn(`Background Fetch '${bgFetch.id}' dibatalkan.`);

  // Informasikan ke user bahwa unduhan dibatalkan
  self.registration.showNotification(`${bgFetch.title} dibatalkan.`, {
    body: 'Unduhan dihentikan oleh pengguna atau sistem.',
    icon: '/images/download-abort-icon.png'
  });
});

💡 Tips: Di event backgroundfetchsuccess, Anda perlu mengakses event.registration.matchAll() untuk mendapatkan semua BackgroundFetchRecord yang berisi Request dan Response dari setiap bagian unduhan. Dari Response, Anda bisa menyimpan data ke IndexedDB atau Cache Storage untuk akses offline.

5. Memantau Progress dan Status Fetch

Salah satu fitur terbaik dari Background Fetch adalah kemampuannya untuk memantau progres transfer secara real-time dan memberikan umpan balik kepada pengguna.

Anda bisa mendengarkan event progress pada objek BackgroundFetchRegistration yang dikembalikan saat Anda memulai fetch.

// Lanjutan dari kode di halaman web Anda
bgFetch.addEventListener('progress', () => {
  const downloaded = bgFetch.downloaded; // Jumlah byte yang sudah diunduh
  const uploaded = bgFetch.uploaded;     // Jumlah byte yang sudah diunggah
  const total = bgFetch.downloadTotal;   // Total byte yang diharapkan (dari options)

  if (total > 0) {
    const progressPercent = Math.round((downloaded / total) * 100);
    console.log(`Progress untuk '${bgFetch.id}': ${progressPercent}%`);
    // 🎯 Update elemen UI Anda (progress bar, teks status) di sini
    document.getElementById('download-status').innerText = `Mengunduh: ${progressPercent}%`;
    document.getElementById('download-progress-bar').value = progressPercent;
  } else {
    console.log(`Progress untuk '${bgFetch.id}': ${downloaded} bytes diunduh.`);
  }

  // Anda juga bisa memeriksa status fetch
  console.log('Status:', bgFetch.result || 'in-progress'); // "success", "failure", atau null jika masih berjalan
});

Dengan informasi ini, Anda dapat membangun antarmuka pengguna yang dinamis untuk menunjukkan status unduhan atau unggahan kepada pengguna, bahkan setelah mereka kembali ke aplikasi setelah beberapa waktu.

6. Best Practices dan Pertimbangan

Untuk implementasi Background Fetch API yang optimal, perhatikan beberapa hal berikut: