async/await & Error Handling
Promise-এর উপর সিনট্যাক্স sugar — sync-এর মতো দেখায়
1. async Functions Always Return Promises
async function greet() {
return "hello"; // auto-wrapped in Promise
}
greet().then(console.log); // "hello"
// Throw inside async = rejected promise
async function boom() {
throw new Error("oops");
}
boom().catch(e => console.log("caught:", e.message));
async function Promise return করে। ভেতরে কোনো error throw করলে সেটি rejected promise হয়।2. await — Pause Until Settled
const wait = (ms, v) => new Promise(r => setTimeout(() => r(v), ms));
async function flow() {
const a = await wait(10, 1);
const b = await wait(10, 2);
const c = await wait(10, 3);
return a + b + c;
}
flow().then(console.log); // 6
3. try / catch Around await
async function load() {
try {
const data = await Promise.reject(new Error("network"));
return data;
} catch (err) {
console.log("handled:", err.message);
return null;
} finally {
console.log("cleanup");
}
}
load().then(v => console.log("value:", v));
4. The Sequential-Loop Trap
Awaiting inside a loop runs items one after another. If they're independent, run them in parallel with Promise.all.
const wait = (ms, v) => new Promise(r => setTimeout(() => r(v), ms));
(async () => {
const ids = [1, 2, 3];
// Sequential — ~150 ms total
const t1 = Date.now();
for (const id of ids) await wait(50, id);
console.log("sequential:", Date.now() - t1);
// Parallel — ~50 ms total
const t2 = Date.now();
await Promise.all(ids.map(id => wait(50, id)));
console.log("parallel :", Date.now() - t2);
})();
for (const x of arr) await fetch(x) is sequential. If the requests are independent, this is 10× too slow. Use await Promise.all(arr.map(fetch)).
5. Top-Level Await
Inside an ES module you can use await at the top level — no wrapper IIFE needed.
// app.mjs
const data = await fetch("/api/feed").then(r => r.json());
export default data;
6. Mixing Sync & Async Errors
async function parseAndFetch(s) {
try {
const obj = JSON.parse(s); // sync throw
const data = await fakeNet(obj.id); // async reject
return data;
} catch (e) {
console.log("caught:", e.message);
}
}
async function fakeNet(id) {
if (!id) throw new Error("id missing");
return `fetched #${id}`;
}
parseAndFetch("not-json");
parseAndFetch('{"id":0}');
parseAndFetch('{"id":42}').then(console.log);
7. Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
async | Marks a function so it always returns a Promise. | Function-কে চিহ্নিত করে — সবসময় Promise ফেরত দেয়। |
await | Pauses the async function until the awaited Promise settles. | Promise settle না হওয়া পর্যন্ত function pause। |
try/catch | Sync error trap — also catches errors thrown by await. | Sync error catch করে; await-এর error-ও। |
| Sequential | Awaiting one task at a time inside a loop — slower. | Loop-এ এক-এক করে await করা — slow। |
| Parallel | Running independent tasks together with Promise.all. | Independent task একসাথে চালানো। |
| Top-level await | await at the top of an ES module. | ES module-এর top-level-এ await। |
| Fire-and-forget | Calling an async function without await — risky. | await ছাড়া async call — error চাপা পড়ে। |
| For-await-of | Iterates over an async iterable, awaiting each value. | Async iterable-এর প্রতিটি value await করে। |
await Promise.all([...]) ব্যবহার করুন; loop-এ একে একে await করলে অপ্রয়োজনে slow। ES module-এ top-level await সরাসরি কাজ করে।
8. Practice Problems
- Write an async function that returns 42.
✨ Show Answer
a1.jsasync function f() { return 42; } f().then(console.log); - Use
awaiton a 50ms timer.✨ Show Answer
a2.js(async () => { await new Promise(r => setTimeout(r, 50)); console.log("done"); })(); - Catch a rejected promise with try/catch.
✨ Show Answer
a3.js(async () => { try { await Promise.reject("x"); } catch (e) { console.log("caught:", e); } })(); - Run three independent waits in parallel.
✨ Show Answer
a4.jsconst w = (v, ms) => new Promise(r => setTimeout(() => r(v), ms)); (async () => { const [a, b, c] = await Promise.all([w(1, 10), w(2, 10), w(3, 10)]); console.log(a, b, c); })(); - Show that throwing inside an async function makes the returned promise reject.
✨ Show Answer
a5.jsasync function bad() { throw new Error("x"); } bad().catch(e => console.log("rejected:", e.message)); - Compare sequential and parallel timing for 5 50-ms tasks.
✨ Show Answer
a6.jsconst w = (ms) => new Promise(r => setTimeout(r, ms)); (async () => { const ms = [50,50,50,50,50]; let t = Date.now(); for (const n of ms) await w(n); console.log("seq:", Date.now() - t); t = Date.now(); await Promise.all(ms.map(w)); console.log("par:", Date.now() - t); })(); - Promisify
setTimeoutassleepand use with await.✨ Show Answer
a7.jsconst sleep = ms => new Promise(r => setTimeout(r, ms)); (async () => { console.log("start"); await sleep(30); console.log("after 30ms"); })(); - Build
retry(fn, n)using async/await.✨ Show Answer
a8.jsasync function retry(fn, n) { for (let i = 0; i < n; i++) { try { return await fn(); } catch (e) { if (i === n - 1) throw e; } } } let i = 0; retry(() => ++i < 3 ? Promise.reject("x") : Promise.resolve("ok"), 5) .then(console.log); - Show the wrong way: forgetting to await an async function.
✨ Show Answer
a9.jsasync function val() { return 42; } async function main() { const v = val(); // missing await — v is a Promise console.log("got:", v); console.log("awaited:", await v); } main(); - Use try/catch/finally to log "cleanup" on both success and failure.
✨ Show Answer
a10.js(async () => { try { await Promise.reject("err"); } catch (e) { console.log("caught", e); } finally { console.log("cleanup"); } })(); - Why is awaiting in a for-of loop sometimes correct (despite being slower)?
✨ Show Answer
Answer: Sometimes order matters or each step depends on the previous result (e.g. paginated APIs, transactional writes). In those cases sequential is the right choice. Use
Promise.allonly when items are independent. - Show top-level await syntactically (with explanation, since runner can't simulate modules).
✨ Show Answer
Inside an ES module file (
.mjsor with"type": "module"), this works at the top level:// app.mjs const config = await fetch("/config.json").then(r => r.json()); export default config; - Write a function that fetches three URLs in parallel and returns when ALL settle.
✨ Show Answer
a13.jsconst fake = (v, ms, fail) => new Promise((res, rej) => setTimeout(() => fail ? rej(v) : res(v), ms)); (async () => { const r = await Promise.allSettled([ fake("a", 10), fake("b", 10, true), fake("c", 10) ]); console.log(r); })(); - Implement a simple async queue with concurrency 1.
✨ Show Answer
a14.jsfunction serial() { let last = Promise.resolve(); return task => (last = last.then(task, task)); } const run = serial(); run(() => new Promise(r => setTimeout(() => { console.log("a"); r(); }, 30))); run(() => new Promise(r => setTimeout(() => { console.log("b"); r(); }, 30))); - Convert a Promise chain (
.then.then.catch) to async/await.✨ Show Answer
a15.jsconst step = v => Promise.resolve(v + 1); (async () => { try { const a = await step(1); const b = await step(a); const c = await step(b); console.log(c); } catch (e) { console.log("err", e); } })(); - In one paragraph, explain why async/await beats raw Promises.
✨ Show Answer
Answer: async/await reuses
try/catchfor error handling, eliminates the "forgot to return" trap inside.then, lets you mix sync and async errors in one place, and keeps control flow visually linear so you can use ordinaryif/forwith awaits inline. Underneath, it is still Promises — so all the combinators still work — but the surface code is dramatically easier to read and refactor.
Summary — Module 23
async functions return Promises. await pauses inside them until the awaited Promise settles. try/catch/finally handles errors uniformly. Run independent work in parallel with Promise.all rather than sequentially in a loop. ES modules support top-level await.
Promise.all; sequence-এ for-of।