# Background Fetch API

The Background Fetch API allows you to manage downloads and uploads that may take a significant amount of time, such as movies, audio files, or software updates. It operates in the background, meaning the transfer continues even if the user closes the application or the browser.

## 1. The Concept

Standard `fetch()` requests are tied to the page's lifecycle. If the user closes the tab, the download stops. The Background Fetch API delegates the fetch operation to the browser's service worker, allowing it to persist independently of the page.

## 2. Starting a Background Fetch

You initiate a background fetch from the main page (or service worker) using the `ServiceWorkerRegistration`.

```javascript
navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch('my-download-id', ['/video.mp4'], {
    title: 'Downloading Video',
    icons: [{
      src: '/icon.png',
      sizes: '192x192',
      type: 'image/png'
    }],
    downloadTotal: 60 * 1024 * 1024 // Optional: Expected size in bytes
  });
});
```

## 3. Monitoring Progress

You can monitor the progress of the fetch directly from the `BackgroundFetchRegistration` object returned by `fetch()`.

```javascript
bgFetch.addEventListener('progress', () => {
  if (!bgFetch.downloadTotal) return;
  
  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});
```

## 4. Service Worker Events

The Service Worker handles the completion or failure of the fetch.

### `backgroundfetchsuccess`
Fired when all requests in the fetch are successful.

```javascript
// service-worker.js
self.addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Open the cache
    const cache = await caches.open('my-downloads');
    
    // Get all records
    const records = await bgFetch.matchAll();
    
    // Move responses to cache
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    await Promise.all(promises);
    
    // Update UI notification
    event.updateUI({ title: 'Download Complete!' });
  }());
});
```

### `backgroundfetchfail`
Fired if at least one request fails.

```javascript
self.addEventListener('backgroundfetchfail', (event) => {
  console.log('Background Fetch failed');
  event.updateUI({ title: 'Download Failed' });
});
```

### `backgroundfetchclick`
Fired when the user clicks the browser-provided download notification.

```javascript
self.addEventListener('backgroundfetchclick', (event) => {
  event.notification.close();
  clients.openWindow('/downloads');
});
```

[[programming/javascript/vanilla/javascript]]
[[programming/javascript/vanilla/service-workers-and-pwa]]
[[programming/javascript/vanilla/ajax-fetch]]