Some work takes time: reading a file, asking a server, waiting for a timer. A Promise represents a result that will arrive later: it is pending, then fulfilled (with a value) or rejected (with an error).
Promises
new Promise((resolve, reject) => ...)
Create a promise: call resolve with a value or reject with an error.
const wait = (ms, value) => new Promise((resolve) => setTimeout(() => resolve(value), ms));
wait(10, "done after 10 ms").then((v) => console.log(v));
console.log("this prints first");
Output:
this prints first
done after 10 ms
then, catch, finally
then receives the value; catch the error; finally runs either way. Each returns a new promise, so you can chain.
Promise.resolve(5)
.then((n) => n * 2)
.then((n) => { console.log("got", n); throw new Error("oops"); })
.catch((e) => { console.log("caught", e.message); return "recovered"; })
.finally(() => console.log("cleanup"))
.then((v) => console.log(v));
Output:
got 10
caught oops
cleanup
recovered
async / await
async functions and await
await pauses the function until a promise settles. An async function always returns a promise. Use try/catch for errors.
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
async function main() {
console.log("start");
const a = await wait(10, "A");
const b = await wait(10, "B");
console.log(a + b);
try {
await Promise.reject(new Error("failed"));
} catch (e) {
console.log("caught:", e.message);
}
}
main().then(() => console.log("finished"));
Output:
start
AB
caught: failed
finished
Running several at once
Promise.all([...])
Waits for all to succeed (and gives the results in order), or fails as soon as one fails.
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
const t0 = Date.now();
Promise.all([wait(30, "a"), wait(10, "b"), 3]).then((r) => console.log(r, Date.now() - t0 < 60));
Output:
[ 'a', 'b', 3 ] true
Promise.allSettled([...])
Waits for all, whether they succeed or fail, and reports each outcome.
Promise.allSettled([Promise.resolve(1), Promise.reject(new Error("no")), 3]).then((r) => console.log(r.map((x) => x.status)));
Output:
[ 'fulfilled', 'rejected', 'fulfilled' ]
Promise.race and Promise.any
race: the first to settle. any: the first to succeed.
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
Promise.race([wait(30, "slow"), wait(5, "fast")]).then((v) => console.log("race:", v));
Promise.any([Promise.reject(new Error("x")), wait(10, "ok")]).then((v) => console.log("any:", v));
Output:
race: fast
any: ok
Sequential versus parallel
Awaiting in a loop runs one after another; start all first to run them together.
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
async function run() {
let t = Date.now();
await wait(30); await wait(30);
console.log("sequential >= 60ms:", Date.now() - t >= 55);
t = Date.now();
await Promise.all([wait(30), wait(30)]);
console.log("parallel < 55ms:", Date.now() - t < 55);
}
run();
Output:
sequential >= 60ms: true
parallel < 55ms: true
Timeouts and retries
A timeout wrapper and a retry
Small, useful patterns built from promises.
const wait = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms));
const timeout = (p, ms) => Promise.race([p, new Promise((_, rej) => setTimeout(() => rej(new Error("timeout")), ms))]);
timeout(wait(50), 10).catch((e) => console.log(e.message));
async function retry(fn, times) {
for (let i = 1; i <= times; i++) {
try { return await fn(i); } catch (e) { if (i === times) throw e; }
}
}
retry(async (i) => { if (i < 3) throw new Error("fail"); return "ok on try " + i; }, 5).then(console.log);
Output:
ok on try 3
timeout
Order of execution
JavaScript runs the current code to the end first. Then microtasks (promise callbacks) run, then timers.
console.log("1 sync");
setTimeout(() => console.log("4 timer"), 0);
Promise.resolve().then(() => console.log("3 promise"));
queueMicrotask(() => console.log("3b microtask"));
console.log("2 sync");
Output:
1 sync
2 sync
3 promise
3b microtask
4 timer
Always handle rejections (
catchortry/catch). An unhandled rejection can crash Node.js and hides bugs in browsers.
Try it yourself
- Write
delay(ms)that returns a promise, and use it to print three lines one second apart. - Run three delays in parallel with
Promise.alland measure the time. - Write a function that tries to fetch a URL and returns a default if it fails (use
try/catch).
Final lesson: regular expressions, DOM essentials and handy extras.

Comments
Loading comments…