How to Cancel Ongoing Promises in JavaScript with AbortController
This article explains why native JavaScript Promises cannot be cancelled, introduces the AbortController API as the standard solution, and provides practical examples for using it with fetch and custom asynchronous functions to safely abort operations and improve application robustness.
In modern frontend development, Promise and async/await are the foundation for handling asynchronous operations, but a common tricky problem is how to cancel a Promise that has already started.
For example, a user may initiate a data request and then navigate away before it completes, or type quickly in a search box where the previous request should be cancelled and only the latest kept. In such scenarios, cancelling an ongoing Promise becomes essential.
Core Issue: Why a Promise Itself Cannot Be Cancelled
A Promise represents the final result of an asynchronous operation. Once its state changes from pending to either fulfilled (success) or rejected (failure), the state never changes again.
Promise does not provide a cancellation mechanism for two reasons:
State is irreversible : This is a core specification of Promise. Once the state changes, the result is fixed.
Single responsibility : A Promise’s responsibility is to deliver a value and its state, not to control the execution of the underlying asynchronous operation. The function that initiates the async work (e.g., fetch) is the executor.
Analogy: sending a letter (starting a Promise) cannot be magically withdrawn from the postal system; you can only choose to ignore it when it arrives.
Our goal is to implement such an “ignore” mechanism and, as much as possible, notify the underlying async operation to stop, saving resources.
AbortController
AbortControlleris the best‑practice and standard way to cancel Promises today. It was originally designed to cancel fetch requests, but its generic nature allows integration with any asynchronous operation.
AbortController works as follows:
Create an AbortController instance. controller.signal: an AbortSignal object that can be passed to async functions that support cancellation (e.g., fetch). controller.abort(): call this method to emit an “abort” signal.
When abort() is called, the signal notifies all listeners. For fetch, it automatically aborts the network request and causes the Promise to reject with an AbortError.
1. Using with fetch
This is the most common usage of AbortController.
In async/await syntax the pattern is equally clear.
2. Using AbortController in Custom Promises
You can also make your own asynchronous functions support AbortSignal.
Principle:
Your function needs to accept signal as a parameter.
At key points in the async operation, check signal.aborted. If it is true, exit early.
Use signal.addEventListener('abort', ...) to register cleanup logic (e.g., clearing timers).
Advantages:
Official standard : Defined by W3C and WHATWG.
Truly aborts underlying operation : fetch aborts the network connection, and custom functions can clean up resources (e.g., clear timers), avoiding unnecessary waste.
Clear semantics : Using the dedicated AbortError distinguishes “cancellation” from other errors, making code more robust.
Strong composability : A single AbortSignal can be passed to multiple Promises, enabling batch cancellation.
Although the core design of Promise makes its state immutable, by leveraging the powerful AbortController pattern we can effectively control and terminate asynchronous flows, writing more robust and efficient applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaScript
Provides JavaScript enthusiasts with tutorials and experience sharing on web front‑end technologies, including JavaScript, Node.js, Deno, Vue.js, React, Angular, HTML5, CSS3, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
