signalsfetch-apiabortcontroller

How to combine AbortController and AbortSignal?


To specify a timeout of a fetch request, we can use a AbortSignal.timeout() signal:

await fetch(url, {
  signal: AbortSignal.timeout(10 * 1000),

});

But this is just a standalone signal, not a controller.

What if I also want to control the request somewhere else in the code, and abort the request? Normally I would use AbortController for that:

const abortController = new AbortController();
await fetch(url, {
  signal: abortController.signal,

});

// now I can call abortController.abort();

But now I lose the timeout convenience. Is there any way to have both, without manually handling the timeout (with setTimeout)?


Solution

  • You can use AbortSignal.any - it is relatively new (as of 2024), though, so keep that in mind. See the documentation up at https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static.

    Usage is:

    const currentRequestController = new AbortController();
    
    // ...
    
    const response = await fetch('https://example.com/some/path', {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
      signal: AbortSignal.any([AbortSignal.timeout(1000), currentRequestController.signal]),
    });
    
    // ...
    
    // can abort later or the timeout will fire... whichever occurs first
    currentRequestController.abort()