Terminating hung Promises in javascript
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
A hung Promise is a Promise that stays pending longer than your program can tolerate. The important detail is that you cannot forcibly kill a Promise object itself; you can only stop or ignore the underlying async operation that the Promise represents.
Why Promises Cannot Be “Terminated” Directly
A Promise is just a container for eventual success or failure. Once created, it has no built-in cancellation method. That design keeps Promises simple, but it means cancellation must be designed into the operation around them.
If a fetch call stalls, the Promise does not know how to cancel the network layer by itself. If a timer-based task hangs, the Promise cannot magically clear the timer. Your code has to provide a way to stop the underlying work.
That leads to two practical strategies:
- cancel the operation when the API supports cancellation
- stop waiting after a timeout and ignore the late result
The first option is better because it releases resources. The second only protects the caller.
Use AbortController for Supported APIs
Modern web APIs, including fetch, support cancellation through AbortController. You create a controller, pass its signal into the async call, and abort it if the work takes too long.
This is real cancellation. The request is told to stop, and the Promise rejects with an abort-related error.
Promise.race Only Stops Waiting
A common pattern is racing an operation against a timeout Promise.
This protects the caller from waiting forever, but it does not cancel slowTask. The timer still runs in the background. That is why Promise.race is a timeout wrapper, not a termination mechanism.
Use it when the operation has no cancellation API, but understand the tradeoff.
Build Cooperative Cancellation Into Your Own Code
For custom async functions, the best design is cooperative cancellation. Accept an AbortSignal or similar token and check it during the operation.
This pattern scales well. It works for timers, polling loops, stream processing, and long-running workflows because the async code knows how to clean up after itself.
Design for Cleanup, Not Just Failure
Hung async work is often more than a user-facing timeout problem. It can leave open sockets, active intervals, progress indicators, or stale state updates. When you add cancellation, include cleanup logic.
For example, if an operation updates UI state when it completes, guard against late completion after the user has navigated away. If a timeout causes the caller to move on, the eventual result should not still mutate state that is no longer relevant.
A useful rule is to separate these concerns:
- timeout decides how long the caller waits
- cancellation stops underlying work
- cleanup releases resources and prevents stale updates
When those three concerns are handled explicitly, async code becomes much easier to debug.
Common Pitfalls
Assuming Promise.race cancels the losing Promise is the most common mistake. It does not.
Aborting the caller without aborting the underlying work can still leak resources. If the API supports AbortSignal, use it.
Ignoring cleanup is another frequent problem. Clear timers, detach listeners, and prevent late state updates after cancellation.
Creating custom cancellation flags without a consistent contract also causes bugs. Prefer AbortController unless you have a strong reason to invent your own pattern.
Summary
- a Promise cannot be forcibly terminated by itself
- real cancellation requires support from the underlying async operation
- '
AbortControlleris the standard solution for cancellable web APIs' - '
Promise.raceadds a timeout but does not stop the losing task' - cooperative cancellation and cleanup are the key to reliable async code
Related reading
- Test asynchronous functionality in Jasmine 2.0.0 with done
- Testing async function with jasmine
- Testing Complex Asynchronous Redux Actions
- tf.data Parallelize loading step
- Tersest way to create an array of integers from 1..20 in JavaScript
- Test if an element is present using Selenium WebDriver
- Terminating mvn spring-bootrun doesn't stop tomcat
- Terraform and Helm3 Error Kubernetes cluster unreachable
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.