Touffy / client-zip

A client-side streaming ZIP generator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[QUESTION] How to handle Download cancellations with Service Worker

JulianBerger opened this issue · comments

Hi,
I use client-zip to download multiple large files over a service worker like in the worker.js example.

I just wondered if it is possible to propagate a cancel download event of the archive file to the fetch requests in the service worker so they don't continue running after the archive got cancelled.

I just found this issue: w3c/ServiceWorker#1544 and i'm wondering if it is possible at all in todays browsers regarding your latest Output stream cancellation commit #58.

When the Service Worker's client cancels the download, that should cancel the Zip stream from the Worker's point of view.

As you noticed, the output stream cancellation should now throw an error up the chain of async generators that makes up downloadZip (I haven't actually tested it yet).

So at the source, if you passed an (async) iterable to downloadZip, you can catch that error in there and trigger the AbortSignal for any ongoing fetch. Here is a simplified example :

// assuming that `urls` is an array of URLs for the files
async function* source() {
  const downloadController = new AbortController()
  const { signal } = downloadController

  // of course you should not generally start all the requests at once like this
  // but it's easier to show why the signal is necessary
  const promises = urls.map(url => fetch(url, { signal }))
  try {
    for (const promise of promises) yield await promise
  } catch(error) {
    // this will immediately cancel ALL the requests, not just the request
    // whose body is currently consumed by downloadZip (if any)
    downloadController.abort(error)
  }
}
event.respondWith(downloadZip(source()))

As stated in the comment, you should probably not fetch every file immediately, but you can use a stream instead and still use the same signal for all the files, and trigger the signal when you catch an error just like in the example.