Async/Await — Synchronous Look for Async Code
"The Syntax Sugar of Dreams"
আমরা Callback Hell দেখেছি, Promise Chaining দেখেছি। এখন আমরা দেখব জাভাস্ক্রিপ্টের আধুনিক এবং সবচেয়ে পরিষ্কার রূপ—Async/Await।
এটি আসলে নতুন কোনো টেকনোলজি নয়। এটি Promises-এর ওপরেই তৈরি একটি মোড়ক (Syntax Sugar), যা আমাদের অ্যাসিনক্রোনাস কোডকে দেখতে একদম সিঙ্ক্রোনাস কোডের মতো করে দেয়। কোড হবে ক্লিন, পড়া হবে গল্পের মতো।
⭐ ১. Async/Await আসলে কী? (Under the Hood)
দুটি নতুন কিওয়ার্ড:
- async Function: ফাংশনের আগে async লিখলে সেটি অটোমেটিক একটি Promise রিটার্ন করে
- await Keyword: এটি কেবল async ফাংশনের ভেতরেই কাজ করে। এটি জাভাস্ক্রিপ্টকে বলে, "প্রমিজটা Resolve হওয়া পর্যন্ত অপেক্ষা করো, তারপর পরের লাইনে যাও।"
The Magic Transformation
// Promise Way
function getData() {
return fetch('/api').then(res => res.json());
}
// Async/Await Way (Same functionality)
async function getData() {
const res = await fetch('/api'); // এখানে পজ হবে
const data = await res.json(); // এখানে আবার পজ হবে
return data;
}
Senior Insight:
await কোডকে পজ (pause) করে ঠিকই, কিন্তু এটি Main Thread বা ব্রাউজারকে ব্লক করে না। এটি ব্যাকগ্রাউন্ডে অপেক্ষা করে এবং Call Stack খালি করে দেয়।
⭐ ২. Error Handling: The try-catch Block
Promise-এ আমাদের .catch() চেইন করতে হতো। কিন্তু async/await এ আমরা সাধারণ জাভাস্ক্রিপ্ট try-catch ব্যবহার করতে পারি।
async function fetchUserData() {
try {
const response = await fetch("https://api.wrong-url.com");
const data = await response.json();
console.log(data);
} catch (error) {
// যেকোনো এরর (Network fail, JSON parse error) এখানে ধরা পড়বে
console.error("Oops! Something went wrong:", error.message);
} finally {
console.log("Loading stopped...");
}
}
দেখতে একদম সিঙ্ক্রোনাস কোডের মতো, তাই না?
⭐ ৩. The Big Trap: Sequential vs Parallel Execution 🐢 vs 🐇
এটি ইন্টারভিউ এবং পারফরম্যান্সের জন্য সবচেয়ে গুরুত্বপূর্ণ টপিক। জুনিয়ররা প্রায়ই সব জায়গায় await বসিয়ে কোড স্লো করে ফেলে।
❌ Sequential (Waterfall) - Slow
ধরা যাক তোমার ৩টি API কল করতে হবে।
async function loadDashboard() {
console.time("Sequential");
const user = await getUser(); // ২ সেকেন্ড লাগল
const posts = await getPosts(); // ২ সেকেন্ড লাগল
const comments = await getComments(); // ২ সেকেন্ড লাগল
// মোট সময়: ২+২+২ = ৬ সেকেন্ড!
console.timeEnd("Sequential");
}
✅ Parallel (Promise.all) - Fast
যেহেতু API কলগুলো একে অপরের ওপর নির্ভরশীল নয়, তাই আমরা একসাথে কল করব।
async function loadDashboardFast() {
console.time("Parallel");
// তিনটি প্রমিজ একসাথে শুরু হলো
const userPromise = getUser();
const postsPromise = getPosts();
const commentsPromise = getComments();
// একসাথে রেজাল্টের জন্য অপেক্ষা
const [user, posts, comments] = await Promise.all([
userPromise, postsPromise, commentsPromise
]);
// মোট সময়: ম্যাক্সিমাম যেটা (২ সেকেন্ড)!
console.timeEnd("Parallel");
}
Decision:
যখন একটার ডাটা অন্যটার ইনপুট হিসেবে দরকার নেই, তখন সবসময় Parallel এক্সিকিউশন করবে।
⭐ ৪. Looping with Async/Await (The Danger Zone) ⚠️
লুপের ভেতরে async ব্যবহার করা একটু ট্রিকি।
❌ forEach (কাজ করবে না!)
forEach অ্যাসিনক্রোনাস কোডের জন্য অপেক্ষা করতে পারে না। সে সব রিকোয়েস্ট একসাথে ফায়ার করে চলে যায়।
const ids = [1, 2, 3];
ids.forEach(async (id) => {
await saveData(id); // ❌ অপেক্ষা করবে না! উল্টাপাল্টা অর্ডারে হবে।
});
console.log("Done"); // লুপ শেষ হওয়ার আগেই "Done" প্রিন্ট হবে।
✅ for...of (Sequential / One by One)
যদি তোমার একটার পর একটা সেভ করার দরকার হয়।
for (const id of ids) {
await saveData(id); // ✅ একটার কাজ শেষ হবে, তারপর পরেরটা শুরু হবে
}
🚀 map + Promise.all (Parallel / Super Fast)
যদি সব একসাথে সেভ করতে চাও।
const promises = ids.map(id => saveData(id)); // Array of Promises
await Promise.all(promises); // সব একসাথে শেষ হবে
⭐ ৫. Advanced Patterns (Senior Mindset)
🔥 Retry Pattern (নেটওয়ার্ক ফেইল করলে)
যদি API ফেইল করে, সাথে সাথে এরর না দিয়ে ৩ বার চেষ্টা করো।
async function retryOperation(fn, retries = 3) {
try {
return await fn(); // সফল হলে রিটার্ন করো
} catch (err) {
if (retries <= 1) throw err; // আর সুযোগ নেই, এরর দাও
console.log(`Retrying... attempts left: ${retries - 1}`);
return retryOperation(fn, retries - 1); // রিকার্সন
}
}
// Usage
await retryOperation(() => fetch("/api/data"));
🔥 Timeout Guard (System Protection)
যদি API রেসপন্স দিতে ১০ সেকেন্ডের বেশি লাগায়, তবে আমরা আর অপেক্ষা করব না।
const timeout = (ms) => new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout!")), ms)
);
async function fetchWithTimeout(url) {
try {
// যেটা আগে হবে (Data or Timeout) সেটাই জিতবে
const data = await Promise.race([
fetch(url),
timeout(5000) // ৫ সেকেন্ডের টাইমআউট
]);
return data;
} catch (error) {
console.log("Request cancelled:", error.message);
}
}
⭐ ৬. Anti-Patterns (যা কখনো করবে না) 🚫
- Unnecessary Async: যদি ফাংশনের ভেতরে await না থাকে, তবে async দিও না
- Missing Error Handling: try-catch ছাড়া await ব্যবহার করা বিপজ্জনক (অ্যাপ ক্র্যাশ করতে পারে)
- Mixing Styles: .then() এবং await একই কোডে মিশিয়ে ফেলবে না। যেকোনো একটা স্টাইল ফলো করো
🧠 ৭. Senior Interview Questions
Q: await কি Main Thread ব্লক করে?
A: না! await ফাংশনের এক্সিকিউশন পজ করে, কিন্তু ইভেন্ট লুপকে ফ্রি রাখে যাতে সে অন্য কাজ (যেমন ক্লিক হ্যান্ডলিং) করতে পারে।
Q: async ফাংশন থেকে কী রিটার্ন হয়?
A: সবসময় একটি Promise। যদি তুমি return 5 লেখো, সেটা Promise.resolve(5) হয়ে যায়।
🚀 অধ্যায় ১০ সারাংশ (Checklist)
আমরা শিখলাম:
- ✓ Syntax: async ফাংশন প্রমিজ রিটার্ন করে, await প্রমিজ রিজলভের অপেক্ষা করে
- ✓ Safety: try-catch দিয়ে এরর হ্যান্ডলিং করা সহজ
- ✓ Performance: Promise.all দিয়ে প্যারালাল রিকোয়েস্ট হ্যান্ডেল করা
- ✓ Looping: forEach এড়িয়ে for...of বা map ব্যবহার করা
- ✓ Robustness: Retry এবং Timeout প্যাটার্ন ব্যবহার করে সিস্টেমকে স্টেবল রাখা
Next Step: আমরা জাভাস্ক্রিপ্টের লজিক এবং অ্যাসিনক্রোনাস পার্ট শেষ করেছি। এখন আমাদের শিখতে হবে কিভাবে ইউজারের সাথে ইন্টারঅ্যাক্ট করতে হয়। ব্রাউজারের পর্দায় যা দেখি, সেটা ম্যানিপুলেট করার জাদু। পরের অধ্যায়: "DOM Manipulation Mastery"।