Node.js — Cancel Slow Work with AbortController
tinyserve can fetch an update from several mirrors. Asking all of them and keeping the fastest is
easy; what separates a robust version from a leaky one is cancelling the others, and giving
up when everyone is too slow. Node uses the web's
[`AbortController`](https://nodejs.org/api/globals.html#class-abortcontroller) for that:fetch, fs.readFile, timers/promises, child_process, streams and events.once all
accept a signal.
Your task
Write async fastestMirror(mirrors, timeoutMs, download):
- Call
download(mirror, { signal })for every mirror at once. It returns a promise of the
mirror's data, rejects if the mirror is down, and rejects with an AbortError as soon as
signal aborts.
- Resolve with the first successful download. A mirror that is down does not win.
- Once there is a winner, abort every download still running.
- If nothing succeeded after
timeoutMs, abort everything and reject with aTimeoutError
(error.name === 'TimeoutError').
- If every mirror fails before the deadline, reject with the
AggregateErrorof
[`Promise.any`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/any).
The driver reports the result (or the error's name) and which downloads were aborted while
still running.
Tools
AbortSignal.timeout(ms)— a signal that aborts by itself with aTimeoutError.AbortSignal.any([a, b])— aborts when any of the signals aborts (Node 20.3+).signal.reason— what it was aborted with.
Sample tests