Abort Controller - Cancel your API calls.

Typewriter with text "Cancel" printed on the page.
Photo by Markus Winkler / Unsplash

One of the most common parts of frontend development is fetching things. In the modern SPA/Hybrid culture, most of the times, it's data.

How does a fetch call look like?

//Fetch request
fetch('https://jsonplaceholder.typicode.com/posts')
	.then(res => res.json())
	.then(json => console.log(json))

//With a library like axios
axios.get('https://jsonplaceholder.typicode.com/posts')
	.then(res => console.log(res))

However, not all requests are the same. Some are small, some are huge, some take time and some can be stored in the cache. In case of requests that take a lot of time, either due to heavy compute or latency, it can block the microtask queue.

What's the microtask queue?

I'll be going in detail about the microtask queue in a different blogpost. Meanwhile you can read this 'draft' stage article on MDN: In depth: Microtasks and the JavaScript runtime environment.


Sometimes, you don't want to wait for that request. The most common scenario where this might be needed is when the user moves away from that page. In such cases, you do want to cancel the request. So, how do we do that?

Using the AbortController API.

AbortController has a 'signal' property. This is a read-only property passed to the fetch request, which is then used to communicate with the DOM request.

How does this change our fetch request?

const controller = new AbortController();
const signal = controller.signal;

//fetch request
fetch('https://jsonplaceholder.typicode.com/posts', {signal})
	.then(res => res.json())
	.then(json => console.log(json))

controller.abort();

//with a library like axios
axios.get('https://jsonplaceholder.typicode.com/posts', {signal})
	.then(res => console.log(res))

controller.abort();

If you google about axios, you might see examples like below. CancelToken is currently marked deprecated as axios supports AbortController starting v0.22.0.

//axios request with CancelToken
const cancelToken = axios.CancelToken
const source = cancelToken.source()

axios.get('/https://jsonplaceholder.typicode.com/posts/', {cancelToken: source.token});
source.cancel("axios request cancelled.")

controller.abort() or source.cancel() can be triggered on button click events. But the most common scenario is when the user navigates away from the page that is actually making that request. If you're using React, you can do this by returning these in the useEffect.

useEffect(() => {
	const controller = new AbortController();
	const signal = controller.signal;

	fetch('https://jsonplaceholder.typicode.com/posts', {signal})
		.then(res => res.json())
		.then(json => functionThatSetsState(json))
    	.catch(err => {
        	if(err.name === 'AbortError'){
                console.log('request was aborted')
            } else {
                console.log('some other error', err)
            }
    	})
    
	return(() => {
        controller.abort();
    })
}, [])

The error thrown when the request was cancelled can be identified using err.name. This way, if you're displaying the network errors to the users, you can safely ignore errors caused due to cancellation.


How well supported is the AbortController API?

AbortController has been implemented in major browsers. You can refer to caniuse.com for your specific requirement.

Subscribe to Kali

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe