The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Promises make asynchronous JavaScript easier to sequence and reason about: each step returns a new promise, and the value or error it produces flows to the next step. The key is to return asynchronous work from each handler. If you leave it out, the chain cannot wait for that work or pass its result onward.
What a promise represents
A promise is an object representing the eventual outcome of an asynchronous operation. It begins pending, then settles as either fulfilled or rejected. Fulfilled and rejected are the two settled states; once settled, a promise cannot change to the other outcome.
As an Amazon Associate I earn from qualifying purchases.
“Resolved” is not always interchangeable with “fulfilled.” Resolving a promise with a promise-like object, or thenable, makes it adopt that object’s eventual state. For example, Promise.resolve(value) follows a thenable rather than simply fulfilling with the thenable as an ordinary value. See the MDN Promise reference.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallThe Promise constructor takes an executor function that receives resolve and reject. It is useful for adapting work that must explicitly signal success or failure, such as a callback-based API. Most application code should begin with an API that already returns a promise rather than wrapping it in a new constructor. MDN’s guide to using promises describes this as the more common pattern.
#1 Best Overall
How promises flatten callback hell
Callback hell, sometimes called the “pyramid of doom,” is deeply nested code in which each asynchronous callback starts the next operation. The nesting can make the order of work and the path for errors harder to follow. A promise chain lets dependent operations appear one after another at the same indentation level. It changes the structure of the code, not the asynchronous nature of the work.
The following schematic examples use illustrative function names, not a particular API:
// Nested callback shape
getUser(id, (user) => {
getOrders(user, (orders) => {
getTotal(orders, (total) => showTotal(total));
});
});
// Promise chain shape
getUser(id)
.then((user) => getOrders(user))
.then((orders) => getTotal(orders))
.then((total) => showTotal(total))
.catch(showError);
The chain makes the sequence visible without nesting each next step inside the previous callback. Promise reactions also provide a consistent path for forwarding failures, as described in MDN’s promise guide. A peer-reviewed analysis by Madsen, Lhoták, and Tip likewise examines how promise reactions allow sequential-looking code at one level: A Model for Reasoning About JavaScript Promises.
Rank #2
What happens in a promise chain
.then(onFulfilled, onRejected) attaches handlers and returns a different promise. That new promise represents the handler’s completion and adopts its outcome. In practical terms, every handler determines what the next link receives:
- If a handler returns an ordinary value, the next promise fulfills with that value.
- If it returns another promise or thenable, the next promise follows that operation’s eventual outcome.
- If there is no handler for the current settlement, that outcome passes through the link unchanged.
For example, each handler below passes a result to the following handler:
fetchUser(id)
.then((user) => fetchOrders(user.id))
.then((orders) => orders.length)
.then((count) => console.log(count));
The first handler returns fetchOrders(...), so the chain waits for it and passes its fulfilled result—orders—to the next handler. Returning orders.length then makes that number the input to the final handler.
Why a missing return can produce undefined
Consider a handler that starts a promise but does not return it:
fetchUser(id)
.then((user) => {
fetchOrders(user.id); // started, but not returned
})
.then((orders) => console.log(orders));
The first handler completes without returning a value, so its dependent promise fulfills with undefined. The next handler does not receive the orders: the separately started fetchOrders operation is not connected to the chain, and the chain does not wait for it. This disconnected work is often called a floating promise. Return the promise to keep the work and its result in the chain:
fetchUser(id)
.then((user) => {
return fetchOrders(user.id);
})
.then((orders) => console.log(orders));
With an expression-bodied arrow function, the return is implicit: .then((user) => fetchOrders(user.id)). This return behavior is a common source of unexpected undefined values; MDN discusses it in its guide to promise chaining.
Rank #4
How rejection and exceptions move through a chain
A rejection skips fulfillment-only handlers and moves down the chain until a rejection handler is found. An exception thrown inside a .then() handler rejects the promise returned by that .then(), so a later .catch() can handle it. The same general rule applies to failures from returned promises: their rejection becomes the chain’s rejection.
A .catch(handler) is a rejection handler that returns another promise. If its callback finishes normally, that returned promise fulfills with the callback’s return value—or with undefined if the callback returns nothing. In other words, catching an error and returning normally recovers the chain; it does not keep an error flag attached. To log an error while preserving the failure for a caller, throw it again or return a rejected promise:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
loadData()
.then(transform)
.catch((error) => {
report(error);
throw error; // preserve the rejection for the next caller
});
A catch at the end is useful when failures share the same handling. Put a catch nearer to an operation when that operation is optional and a fallback should let the main chain continue. The important distinction is the handler’s outcome: return normally to recover, or throw/return a rejection to continue propagating failure. MDN explains these propagation and recovery rules in its promise guide and Promise reference.
Best Value
When promise handlers run
The executor passed to new Promise(...) runs as part of constructing the promise. By contrast, handlers registered with .then() do not run synchronously in the current call stack—even if the promise is already fulfilled. They are scheduled as microtasks, which run after the current JavaScript stack completes.
Promise.resolve().then(() => console.log("later"));
console.log("now");
This prints now before later. Promises describe and sequence asynchronous outcomes; they do not make CPU-heavy JavaScript run in parallel. MDN covers reaction scheduling in its guide to using promises.
A practical debugging checklist
- The next handler receives
undefined: check whether the preceding handler returns its value or promise. A block-bodied arrow function needs an explicitreturn. - A later step runs before an operation finishes: check whether that operation’s promise is returned from the handler. If it is not, the work is floating outside the chain.
- A fulfillment handler is skipped: trace the chain for a rejection or thrown exception and find the next rejection handler.
- The chain continues after a catch: inspect the catch callback’s result. A normal return recovers; a throw or returned rejection keeps the chain rejected.
- Output appears after a synchronous log: that is expected for a
.then()reaction, which runs as a microtask after the current stack.
These checks follow the promise value and error through each returned promise, rather than treating .then() as a command that merely runs a callback.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




