Axios Cancellation — Complete Guide with Examples
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
How do you cancel an Axios request? Create an AbortController, pass its signal to the request, and call controller.abort().
How do you detect if an error was caused by cancellation? Use axios.isCancel(error) which returns true for CanceledError instances.
Can you cancel multiple requests at once? Yes. Pass the same signal to multiple requests. Aborting the controller cancels all of them.
Is CancelToken still supported? Yes for backwards compatibility, but AbortController is the recommended API.
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
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