Navigation

Node.js

How to Abort Requests with AbortController

Cancel HTTP requests and async operations using AbortController in Node.js 2025

Table Of Contents

Quick Fix: Basic Request Cancellation

// Create AbortController
const controller = new AbortController();

// Make request with signal
const fetchPromise = fetch('https://api.example.com/slow-endpoint', {
  signal: controller.signal
});

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetchPromise;
  const data = await response.json();
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('Request was cancelled');
  }
}

Node.js Built-in Solution: Advanced Abort Patterns

const axios = require('axios');

// Axios with AbortController (v0.22+)
const controller = new AbortController();

axios.get('https://api.example.com/data', {
  signal: controller.signal
})
.then(response => console.log(response.data))
.catch(error => {
  if (axios.isCancel(error)) {
    console.log('Request cancelled:', error.message);
  }
});

// Cancel on user action
document.getElementById('cancelBtn').addEventListener('click', () => {
  controller.abort('User cancelled operation');
});

// Timeout with AbortController
function fetchWithTimeout(url, timeout = 5000) {
  const controller = new AbortController();
  
  const timeoutId = setTimeout(() => {
    controller.abort('Request timeout');
  }, timeout);
  
  return fetch(url, { signal: controller.signal })
    .finally(() => clearTimeout(timeoutId));
}

// Race multiple requests, cancel losers
async function fetchFastest(urls) {
  const controllers = urls.map(() => new AbortController());
  
  const promises = urls.map((url, index) => 
    fetch(url, { signal: controllers[index].signal })
      .then(response => ({ response, index }))
  );
  
  try {
    const { response, index } = await Promise.race(promises);
    
    // Cancel other requests
    controllers.forEach((controller, i) => {
      if (i !== index) controller.abort();
    });
    
    return response;
  } catch (error) {
    // Cancel all if race fails
    controllers.forEach(c => c.abort());
    throw error;
  }
}

// Cleanup on component unmount (React example)
function useApiCall(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    const controller = new AbortController();
    
    fetch(url, { signal: controller.signal })
      .then(res => res.json())
      .then(setData)
      .catch(err => {
        if (err.name !== 'AbortError') {
          console.error(err);
        }
      })
      .finally(() => setLoading(false));
    
    // Cleanup function
    return () => controller.abort();
  }, [url]);
  
  return { data, loading };
}

// Abort multiple related operations
class RequestManager {
  constructor() {
    this.controllers = new Map();
  }
  
  async request(id, url, options = {}) {
    // Cancel previous request with same ID
    this.cancel(id);
    
    const controller = new AbortController();
    this.controllers.set(id, controller);
    
    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal
      });
      this.controllers.delete(id);
      return response;
    } catch (error) {
      if (error.name === 'AbortError') {
        console.log(`Request ${id} was aborted`);
      }
      throw error;
    }
  }
  
  cancel(id) {
    const controller = this.controllers.get(id);
    if (controller) {
      controller.abort();
      this.controllers.delete(id);
    }
  }
  
  cancelAll() {
    this.controllers.forEach(controller => controller.abort());
    this.controllers.clear();
  }
}

// Custom abort with reason
const controller = new AbortController();

controller.signal.addEventListener('abort', () => {
  console.log('Aborted with reason:', controller.signal.reason);
});

controller.abort({ code: 'USER_CANCELLED', message: 'User clicked cancel' });

AbortController solves "cancel pending requests", "component cleanup", and "timeout handling" issues. Built into Node.js 15+ and modern browsers. Works with fetch, axios 0.22+, and Node streams. Alternative: axios CancelToken (deprecated), p-cancelable for promises.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Node.js