A JavaScript Promise is an object representing the eventual completion or failure of an asynchronous operation. Every Promise sits in one of three states: pending, fulfilled (resolved with a value), or rejected (failed with an error reason).
stateDiagram-v2
[*] --> Pending : new Promise()
Pending --> Fulfilled : resolve(value)
Pending --> Rejected : reject(error)
Fulfilled --> [*] : .then() / await
Rejected --> [*] : .catch() / try...catch
Once a Promise settles (fulfilled or rejected), its state is locked permanently and cannot switch again.
Chain transformations cleanly with .then(), handle errors in one place with .catch(), and clean up spinners in .finally(). When fetching multiple independent endpoints at once, run them in parallel with combinators:
Promise.all([...]): Waits for all Promises to fulfill; rejects immediately if any single one rejects.Promise.allSettled([...]): Waits for every Promise to finish and returns { status, value | reason } for each without failing fast.Promise.race([...]): Settles as soon as the fastest Promise fulfills or rejects (useful for request timeouts).function fetchProfile(userId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (userId <= 0) {
reject(new Error("Invalid user ID"));
return;
}
resolve({ id: userId, name: `Learner #${userId}` });
}, 20);
});
}
Promise.all([fetchProfile(1), fetchProfile(2)])
.then((profiles) => console.log("Loaded in parallel:", profiles))
.catch((err) => console.error("Failed:", err.message))
.finally(() => console.log("All profile tasks settled."));
return inside a .then() handler: Without return nextPromise(), the next .then() receives undefined instead of waiting for the inner Promise..catch() on Promise chains: Unhandled rejections print warnings in browsers and can terminate Node.js processes..then() inside .then(): Always return the inner Promise and chain flat .then() calls at the top level (or use async/await).Promise.all() and Promise.allSettled()?Promise.all() rejects as soon as one Promise fails, discarding the rest. Promise.allSettled() always resolves with an array describing every Promise's individual outcome ("fulfilled" or "rejected").
.then() to a Promise that already resolved earlier?Yes! A settled Promise caches its result, so attaching .then() later still receives the resolved value asynchronously on the next microtask.
Promise.any() do?Promise.any(list) resolves with the first fulfilled Promise and ignores rejections unless every Promise in the list fails.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With
Experiment with the code from this lesson in our interactive playground.
You've completed this section! Take a quick 5-question quiz to check your understanding.