Cancel Node.js Fetch Requests with AbortController

Managing long-running or redundant asynchronous tasks is crucial for building efficient backend applications. This article explores how the AbortController API provides a standardized way to cancel asynchronous operations in Node.js, focusing specifically on halting outgoing HTTP requests made with the global fetch API. You will learn the core mechanics of AbortController and see a practical implementation for timeout-based cancellations.

Understanding AbortController and AbortSignal

The AbortController API consists of two primary components: the controller itself and an associated AbortSignal object.

When an asynchronous operation receives an abort signal, it immediately terminates its execution and throws a DOMException named AbortError, which can be caught and handled in a try...catch block.

How to Cancel a Fetch Request in Node.js

To cancel a fetch request, you instantiate an AbortController, pass its signal as an option in the fetch configuration, and call the controller’s .abort() method when a specific condition is met—such as a timeout or a user-initiated event.

Here is a practical code example demonstrating how to implement a request timeout using AbortController in Node.js:

async function fetchWithTimeout(url, timeoutMs = 3000) {
  // 1. Create an instance of AbortController
  const controller = new AbortController();
  const { signal } = controller;

  // 2. Set a timer to trigger the abort after the specified timeout
  const timeoutId = setTimeout(() => {
    controller.abort();
  }, timeoutMs);

  try {
    // 3. Pass the signal to the fetch options
    const response = await fetch(url, { signal });
    const data = await response.json();
    return data;
  } catch (error) {
    // 4. Handle the specific AbortError
    if (error.name === 'AbortError') {
      console.error(`Request timed out and was aborted after ${timeoutMs}ms.`);
    } else {
      console.error('A network or system error occurred:', error.message);
    }
  } finally {
    // 5. Clear the timeout to prevent memory leaks if the request succeeds
    clearTimeout(timeoutId);
  }
}

// Usage
fetchWithTimeout('https://jsonplaceholder.typicode.com/posts/1', 1000);

Key Benefits of Using AbortController