A Promise is an object representing a value that will be available later — or an error. It is the foundation of modern async JavaScript.
Creating and consuming
const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
const fail = (msg) => new Promise((_, reject) => setTimeout(() => reject(new Error(msg)), 5));
wait(10, "done").then((v) => console.log("fulfilled:", v));
fail("boom")
.then(() => console.log("never runs"))
.catch((err) => console.log("rejected:", err.message))
.finally(() => console.log("finally: cleanup either way"));rejected: boom
finally: cleanup either way
fulfilled: doneChaining: every then returns a new promise
Promise.resolve(2)
.then((n) => n * 10) // return a value → next then gets it
.then((n) => new Promise((r) => setTimeout(() => r(n + 1), 5))) // return a promise → waits
.then((n) => {
console.log("value:", n);
throw new Error("oops"); // throw → skips to the next catch
})
.then(() => console.log("skipped"))
.catch((e) => {
console.log("caught:", e.message);
return "recovered"; // catch can recover the chain
})
.then((v) => console.log("after catch:", v));value: 21
caught: oops
after catch: recoveredInside a then handler you… | The returned promise… |
|---|---|
| return a value | fulfils with that value |
| return a promise/thenable | adopts its eventual state |
| throw | rejects with the thrown error |
| return nothing | fulfils with undefined |
Common mistakes
const getData = () => Promise.resolve({ id: 1 });
// 1. forgetting to return → the next then gets undefined
getData()
.then((d) => { getData(); })
.then((v) => console.log("forgot return:", v));
// 2. the executor runs synchronously; resolve only once
const p = new Promise((resolve) => {
console.log("executor runs now");
resolve("first");
resolve("second"); // ignored
});
p.then((v) => console.log("settled with:", v));executor runs now
settled with: first
forgot return: undefinedPromise.resolve / reject / withResolvers
console.log(await Promise.resolve(42));
const p = Promise.resolve(Promise.resolve("nested")); // promises flatten
console.log(await p);
const { promise, resolve } = Promise.withResolvers(); // ES2024
setTimeout(() => resolve("resolved from outside"), 5);
console.log(await promise);
await Promise.reject(new Error("x")).catch((e) => console.log("rejected with", e.message));42
nested
resolved from outside
rejected with xWhat are the states of a Promise?
Why do promise callbacks run asynchronously even if the promise is already resolved?