Handling Asynchronous Operations
1. Using Callbacks
Example: Node-style callback
import fs from "node:fs";
fs.readFile("a.txt", "utf8", (err, data) => {
if (err) return console.error(err);
console.log(data);
});
| Convention | Detail |
|---|---|
| Error first | (err, result) => ... |
| Single invocation | Don't call twice |
2. Working with Promises
| State | Meaning |
|---|---|
| pending | Initial |
| fulfilled | Resolved with value |
| rejected | Failed with reason |
3. Using Async/Await Syntax
Example
async function loadUser(id) {
try {
const res = await fetch(`/users/${id}`);
if (!res.ok) throw new Error(res.statusText);
return await res.json();
} catch (err) { console.error("loadUser failed", err); throw err; }
}
4. Converting Callbacks to Promises (util.promisify)
Example
import { promisify } from "node:util";
import fs from "node:fs";
const readFile = promisify(fs.readFile);
const data = await readFile("a.txt", "utf8");
| Helper | Use |
|---|---|
util.promisify | Wrap (err, data) callback fns |
util.callbackify | Reverse direction |
| Native Promise APIs | Prefer fs/promises, dns/promises, etc. |
5. Handling Promise Rejection
| Pattern | Use |
|---|---|
.catch(handler) | Chain |
try/catch await | Async/await |
process.on("unhandledRejection") | Last resort |
--unhandled-rejections=strict | Crash on unhandled |
6. Using Promise.all for Parallel Execution
| Behavior | Detail |
|---|---|
| Resolves | All settled successfully → array |
| Rejects | First rejection (others keep running) |
7. Using Promise.race for First Resolution
| Resolves With | Notes |
|---|---|
| First settled (fulfill or reject) | Useful for timeouts |
8. Using Promise.allSettled for All Results
Example
const results = await Promise.allSettled(urls.map((u) => fetch(u)));
const ok = results.filter((r) => r.status === "fulfilled");
9. Using Promise.any for First Fulfillment
| Behavior | Detail |
|---|---|
| Resolves | First fulfilled |
| Rejects | All rejected → AggregateError |
10. Understanding Async Error Handling (try-catch)
| Pattern | Notes |
|---|---|
try { await x } catch (e) {} | Catches both sync and async errors |
Forgetting await | Errors escape try/catch |
| Returning vs awaiting | return await preserves stack trace |
11. Using AbortController for Cancellation
Example
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);
const res = await fetch(url, { signal: ctrl.signal });
| API | Purpose |
|---|---|
controller.abort(reason?) | Trigger cancellation |
controller.signal | Pass to async APIs |
12. Using AbortSignal for Timeouts
| Helper | Use |
|---|---|
AbortSignal.timeout(ms) | Auto-abort after delay v17.3+ |
AbortSignal.any([s1, s2]) | Combine signals v20.3+ |