- Web Developer
- Posts
- How to Annul Promises in JavaScript
How to Annul Promises in JavaScript
Creating Cancelable Tasks in JavaScript with Promise.withResolvers and AbortController
In JavaScript, you might already know how to cancel a request: you can use xhr.abort()
for XHR and signal
for fetch. But how do you cancel a regular Promise?
Currently, JavaScript's Promise does not natively provide an API to cancel a regular Promise. So, what we’ll discuss next is how to discard/ignore the result of a Promise.
Method 1: Using the New Promise.withResolvers()
A new API that can now be used is Promise.withResolvers(). It returns an object containing a new Promise object and two functions to resolve or reject it.
Here’s how the code looks:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
Now we can do this:
const { promise, resolve, reject } = Promise.withResolvers();
So we can utilize this to expose a cancel
method:
const buildCancelableTask = <T>(asyncFn: () => Promise<T>) => {
let rejected = false;
const { promise, resolve, reject } = Promise.withResolvers<T>();
return {
run: () => {
if (!rejected) {
asyncFn().then(resolve, reject);
}
return promise;
},
cancel: () => {
rejected = true;
reject(new Error('CanceledError'));
},
};
};
Then we can use it with the following test code:
const sleep = (ms: number) => new Promise(res => setTimeout(res, ms));
const ret = buildCancelableTask(async () => {
await sleep(1000);
return 'Hello';
});
(async () => {
try {
const val = await ret.run();
console.log('val: ', val);
} catch (err) {
console.log('err: ', err);
}
})();
setTimeout(() => {
ret.cancel();
}, 500);
Here, we preset the task to take at least 1000ms, but we cancel it within the next 500ms, so you will see:
Note that this is not true cancellation but an early rejection. The original asyncFn()
will continue to execute until it resolves or rejects, but it doesn’t matter because the promise created with Promise.withResolvers<T>()
has already been rejected.
Reply