The Async Primitive — Same As The Browser
Promises in Node
Promises in Node are the same as the browser. Use them to represent pending async work.
What you'll learn
- Author a function that returns a promise
- Chain with then/catch
- Run in parallel with Promise.all
Promises in Node are identical to browser promises — same spec, same methods. Skip ahead if you already know them; here’s the Node-relevant summary.
A Promise
A value that will be available eventually:
import { readFile } from "node:fs/promises";
const p = readFile("data.txt", "utf8");
// p is a Promise — it hasn't resolved yet
p.then((text) => console.log("got", text))
.catch((err) => console.error("failed", err)); Authoring One
For wrapping callback APIs or doing custom async:
function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
await wait(1000);
console.log("after 1s"); For real code, use timers/promises:
import { setTimeout as wait } from "node:timers/promises";
await wait(1000); The Static Combinators
| Method | Resolves when… |
|---|---|
Promise.all([p1, p2]) | All resolve. Rejects on first rejection. |
Promise.allSettled([p1, p2]) | All settle (resolve OR reject). Never rejects. |
Promise.race([p1, p2]) | The first settles. |
Promise.any([p1, p2]) | The first resolves (ignores rejections). |
const [users, posts, comments] = await Promise.all([
fetch("/users").then(r => r.json()),
fetch("/posts").then(r => r.json()),
fetch("/comments").then(r => r.json()),
]); Three HTTP calls in parallel, one await. Much faster than serial.
Handling Errors
readFile("missing.txt", "utf8")
.then((text) => console.log(text))
.catch((err) => {
if (err.code === "ENOENT") {
console.warn("not there");
} else {
throw err;
}
}); In Promise.all, the first rejection rejects the whole. For “do
all, collect results” semantics, use Promise.allSettled.
Up Next
async/await — promises wearing a more readable shirt.