Use multiple AbortSignals with the Fetch API
Table of Contents
- Table of Contents
- Features
- Browser Support
- Installation
- Usage
- Example
- Troubleshooting
- Credits
- License
Features
- Adds the
timeout
option tofetch()
- Accepts multiple AbortSignals and aborts if any of them are aborted.
- Works with both
AbortController().signal
andAbortSignal.timeout()
- Compatible with
fetch()
and can be used as a replacement in every call.
Browser Support
Latest |
Latest |
Latest |
Latest |
Latest |
Installation
Using npm:
$ npm install fetch-multi-signal
Using yarn:
$ yarn add fetch-multi-signal
Once the package is installed, you can import the function:
import { fetchMS } from 'fetch-multi-signal';
You can also use the default export:
import fetchMS from 'fetch-multi-signal';
You can use fetchMS()
as a drop-in replaement for fetch()
:
import { fetchMS as fetch } from 'fetch-multi-signal';
Usage
async/await
Using const myFunction = async () => {
try {
const res = await fetchMS('url', options);
const json = await res.json();
console.log(json);
} catch (err) {
if (err.name === 'TimeoutError') console.error('Timeout Error');
else if (err.name === 'AbortError') console.error('Abort Error');
} finally {
console.log('done');
}
};
.then()
, .catch()
, and .finally()
Using fetchMS('url', options)
.then((res) => res.json())
.then((json) => console.log(json))
.catch((err) => {
if (err.name === 'TimeoutError') console.error('Timeout Error');
else if (err.name === 'AbortError') console.error('Abort Error');
})
.finally(() => console.log('done'));
Options
// 2 sec timeout
fetchMS('url', { timeout: 2000 })
// 2 sec timeout with 2 AbortSignals
const controller1 = new AbortController();
const controller2 = new AbortController();
const signal1 = controller1.signal;
const signal2 = controller2.signal;
fetchMS('url', { timeout: 2000, signals: [signal1, signal2] })
// 2 sec timeout (using AbortSignal.timeout()) with 2 AbortSignals
const controller1 = new AbortController();
const controller2 = new AbortController();
const signal1 = controller1.signal;
const signal2 = controller2.signal;
const timeoutSignal = AbortSignal.timeout(2000);
fetchMS('url', { signal: timeoutSignal, signals: [signal1, signal2] })
// or fetchMS('url', { signal: signal1, signals: [timeoutSignal, signal2] })
Note: You can use as many AbortSignals as you want in any order.
TypeScript
import { fetchMS, RequestInitMS } from 'fetch-multi-signal';
const options: RequestInitMS = {
timeout: 2000,
signals: [signal1, signal2],
}
fetchMS('url', options)
// .then(... or await fetchMS(...
fetchMSAlt
fetchMSAlt()
works the same as fetchMS()
but uses setTimeout()
to implement the timeout option instead of AbortSignal.timeout()
import { fetchMSAlt } from 'fetch-multi-signal';
fetchMSAlt('url', options)
Example
useEffect()
hook in React
Using with You can abort the fetch request using a timeout and in the clean-up function:
Using the timeout option
useEffect(() => {
const controller = new AbortController();
fetchMS('url', { timeout: 2000, signal: controller.signal });
//.then(...
return () => controller.abort();
}, []);
AbortSignal.timeout()
Using useEffect(() => {
const controller = new AbortController();
const timeoutSignal = AbortSignal.timeout(2000);
fetchMS('url', { signals: [controller.signal, timeoutSignal] });
//.then(...
return () => controller.abort();
}, []);
Troubleshooting
MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal].
1. By default, Node.js has maximum listener limit of 10
. you can increase the limit depending on your use case:
import events from 'events';
events.setMaxListeners(100);
Credits
Inspired by: Proposal: fetch with multiple AbortSignals