Skip to content

Axios Cancellation — Complete Guide with Examples

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you'll learn about Axios request cancellation. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Axios request cancellation lets you abort in-flight HTTP requests using AbortController, preventing wasted bandwidth, handling race conditions, and cleaning up unmounted components.

What You'll Learn

By the end of this tutorial, you'll cancel requests with AbortController, prevent duplicate requests, handle cancellation errors, cancel on component unmount in React, and implement request deduplication.

Why It Matters

Unnecessary network requests waste bandwidth and cause race conditions. A search-as-you-type field fires requests on every keystroke. Without cancellation, old responses may overwrite newer ones, causing incorrect UI state.

Real-World Use

Durga Antivirus Pro cancels scan status polling when the user navigates away from the scan page. This prevents unnecessary network traffic and avoids updating UI for a component that is no longer mounted.

Where This Fits in Your Learning Path

flowchart LR
    A["Transform Data"] --> B["**Cancellation**"]
    B --> C["Progress Events"]
    C --> D["Cookies & Auth"]
    D --> E["Axios Advanced"]
    style B fill:#f97316,stroke:#c2410c,color:#fff
    style A fill:#e5e7eb,stroke:#9ca3af,color:#374151
    style E fill:#22c55e,stroke:#16a34a,color:#fff

Basic Cancellation with AbortController

Create an AbortController and pass its signal to the request config.

const controller = new AbortController()

// Start the request
axios.get('/api/long-request', {
  signal: controller.signal
}).then(response => {
  console.log('Completed:', response.data)
}).catch(error => {
  if (axios.isCancel(error)) {
    console.log('Request was canceled:', error.message)
  }
})

// Cancel the request elsewhere
setTimeout(() => {
  controller.abort()
  console.log('Request canceled after 1 second')
}, 1000)

Expected output: The request starts, but is aborted after 1 second. The catch block receives a CanceledError.

Preventing Duplicate Requests

Cancel the previous request before making a new one.

let currentController = null

async function searchUsers(query) {
  // Cancel any in-flight request
  if (currentController) {
    currentController.abort()
  }

  currentController = new AbortController()

  try {
    const { data } = await axios.get('/api/users', {
      params: { q: query },
      signal: currentController.signal
    })
    return data
  } catch (error) {
    if (!axios.isCancel(error)) {
      throw error
    }
  }
}

// Called on each keystroke
searchUsers('ali')

Expected output: If the user types quickly, only the latest search request completes. Previous in-flight requests are aborted.

Cancellation with Multiple Requests

Cancel multiple requests sharing the same AbortController.

const controller = new AbortController()

const requests = [
  axios.get('/api/users', { signal: controller.signal }),
  axios.get('/api/products', { signal: controller.signal }),
  axios.get('/api/orders', { signal: controller.signal })
]

// Cancel all three requests at once
setTimeout(() => controller.abort('User navigated away'), 300)

try {
  const [users, products, orders] = await Promise.all(requests)
  console.log('All data loaded')
} catch (error) {
  if (axios.isCancel(error)) {
    console.log('Page load canceled:', error.message)
  }
}

Expected output: All three requests are aborted simultaneously when controller.abort() is called.

Handling Cancelation in Interceptors

Detect cancellation in response interceptors for clean error handling.

const api = axios.create({ baseURL: 'https://api.example.com' })

api.interceptors.response.use(
  response => response,
  error => {
    if (axios.isCancel(error)) {
      console.log('Request was canceled:', error.config.url)
      // Don't reject for cancellation - return a special value
      return Promise.resolve({ canceled: true, url: error.config.url })
    }
    return Promise.reject(error)
  }
)

const result = await api.get('/users')
if (result.canceled) {
  console.log('Request was canceled, showing cached data')
}

Expected output: Canceled requests return a special object instead of rejecting, allowing the calling code to handle cancellation gracefully.

Avoid Memory Leaks

Always clean up controllers when components unmount.

// In a framework agnostic pattern
function createCancellableRequest() {
  let controller = null

  return {
    async fetch(url, config = {}) {
      // Cancel previous
      if (controller) controller.abort()

      controller = new AbortController()
      try {
        return await axios.get(url, {
          ...config,
          signal: controller.signal
        })
      } catch (error) {
        if (axios.isCancel(error)) return null
        throw error
      }
    },
    cancel(reason = 'Operation canceled') {
      if (controller) controller.abort(reason)
    }
  }
}

const request = createCancellableRequest()
request.fetch('/api/data')
request.cancel('Component unmounted')

Expected output: The cancellable request wrapper handles cleanup automatically. Calling cancel aborts the current request and prevents memory leaks.

Common Mistakes

1. Using the old CancelToken API (Axios < 0.22)

CancelToken is deprecated in favor of AbortController. Always use AbortController for new code.

2. Not checking axios.isCancel in catch blocks

Without the check, canceled requests trigger generic error handling that may show error UIs.

3. Reusing an AbortController after abort

An aborted controller cannot be reused. Create a new AbortController for each cancellable request group.

4. Forgetting to abort on component unmount

Components that fetch data without cleanup leave dangling requests that try to update unmounted state.

5. Using the same signal for unrelated requests

Signals tie requests together. Aborting one aborts all with that signal. Use separate controllers for independent cancellations.

Practice Questions

  1. How do you cancel an Axios request? Create an AbortController, pass its signal to the request, and call controller.abort().

  2. How do you detect if an error was caused by cancellation? Use axios.isCancel(error) which returns true for CanceledError instances.

  3. Can you cancel multiple requests at once? Yes. Pass the same signal to multiple requests. Aborting the controller cancels all of them.

  4. Is CancelToken still supported? Yes for backwards compatibility, but AbortController is the recommended API.

  5. What happens to an aborted request's response? The promise rejects with a CanceledError. No response is processed or cached.

Challenge

Build a search component with debounce and cancellation. The component should wait 300ms after the last keystroke, cancel any previous request, and ignore responses from stale requests.

FAQ

Can I cancel requests sent with axios.all?

Yes. Pass the same signal to each request in axios.all. Aborting cancels all pending requests.

Does cancellation work in Node.js?

Yes. AbortController is available in Node.js 15+. Axios cancellation works the same in both environments.

Can I cancel a request after it has completed?

No. Cancellation only works on in-flight requests. Completed requests are unaffected.

What is the difference between cancel and timeout?

Timeout rejects after a duration. Cancel aborts manually. Timeout uses the same AbortSignal internally.

How do I pass a custom cancel message?

Pass a string to controller.abort('my reason'). The CanceledError.message will contain 'my reason'.


Mini Project

Build an autocomplete search field that cancels pending requests on each keystroke, debounces input, and ignores stale responses. Show a loading indicator while the request is in flight.

const searchInput = document.querySelector('#search')
const resultsEl = document.querySelector('#results')
let controller = null
let timeoutId = null

searchInput.addEventListener('input', function() {
  const query = this.value.trim()

  clearTimeout(timeoutId)
  resultsEl.textContent = ''

  if (query.length < 2) return

  timeoutId = setTimeout(async () => {
    // Cancel previous request
    if (controller) controller.abort()
    controller = new AbortController()

    resultsEl.textContent = 'Searching...'

    try {
      const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts', {
        params: { q: query },
        signal: controller.signal
      })
      resultsEl.textContent = data.slice(0, 5).map(p => p.title).join('\n')
    } catch (error) {
      if (!axios.isCancel(error)) {
        resultsEl.textContent = 'Error: ' + error.message
      }
    }
  }, 300)
})
<input id="search" type="search" placeholder="Type to search..." class="w-full p-2 border rounded">
<pre id="results" class="mt-2 text-sm text-gray-600"></pre>

What's Next

Track request progress:

Tutorial What You'll Learn
Progress Events Track download progress with Axios
Upload Progress Track file upload progress for large uploads

Related topics: AbortController and AbortSignal API, race condition prevention.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro