Cancel a JavaScript Promise with AbortController

👋 This post also got published on Medium. If you like it, please give it some love a clap over there.

In How to Cancel Your Promise Seva Zaikov has done a nice writeup exploring several attempts on how to cancel promises. After also touching generators and async/await the conclusion is that you can’t actually cancel a promise with the techniques mentioned (you may introduce some workarounds to track the cancelled state yourself, yet that won’t actually cancel an ongoing promise).

At the end of the article the author mentions abortable fetch, but doesn’t dig deeper into it. A shame though, as the shiny AbortController – the driving force behind the abortable fetch – is something which will allow you to actually cancel any promise (and not just fetch)!

To use the AbortController, create an instance of it, and pass its signal into a promise.

// Creation of an AbortController signal
const controller = new AbortController();
const signal = controller.signal;

// Call a promise, with the signal injected into it
doSomethingAsync({ signal })
	.then(result => {
		console.log(result);
	})
	.catch(err => {
		if (err.name === 'AbortError') {
			console.log('Promise Aborted');
		} else {
			console.log('Promise Rejected');
		}
	});

Inside the actual promise you listen for the abort event to be fired on the given signal, upon which the promise will be cancelled.

// Example Promise, which takes signal into account
function doSomethingAsync({signal}) {
	if (signal.aborted) {
		return Promise.reject(new DOMException('Aborted', 'AbortError'));
	}

	return new Promise((resolve, reject) => {
		console.log('Promise Started');

		// Something fake async
		const timeout = window.setTimeout(resolve, 2500, 'Promise Resolved')

		// Listen for abort event on signal
		signal.addEventListener('abort', () => {
			window.clearTimeout(timeout);
			reject(new DOMException('Aborted', 'AbortError'));
		});
	});
}

With this set up, you can call controller.abort(); from anywhere you like in order to abort/cancel the promise:

document.getElementById('stop').addEventListener('click', (e) => {
	e.preventDefault();
	controller.abort();
});

Below is a combined example with two buttons. The “start” button starts a promise which resolves after 2.5 seconds. When hitting “stop/abort” during that timeframe however, the promise will be cancelled.

See the Pen AbortController Example by Bramus (@bramus) on CodePen.

My personal nitpick with AbortController is the fact that it’s part of the DOM spec, and not the ECMAScript Spec. This makes it a browser feature, not a language feature. There once was a proposal for cancelable promises, yet it got withdrawn at Stage-1.

AbortController is available in Firefox 57 and Edge 16. Chrome and Safari are still working on it.

MDN: AbortController
WhatWG DOM Spec: Aborting Ongoing Activities →

Did this help you out? Like what you see?
Thank me with a coffee.

I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

BuymeaCoffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Join the Conversation

2 Comments

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.