Asynchronous JavaScript & The Event Loop

"The Heartbeat of JavaScript"

জাভাস্ক্রিপ্ট জগতটা একটু অদ্ভুত। একদিকে বলা হয় এটি Single-Threaded (একবারে একটার বেশি কাজ করতে পারে না), আবার অন্যদিকে এটি একসাথে হাজার হাজার রিকোয়েস্ট হ্যান্ডেল করছে (Async)।

এই অধ্যায়ে আমরা জাভাস্ক্রিপ্টের ইঞ্জিনের হুড খুলে দেখব ভেতরে আসলে কী ঘটছে। এটা না বুঝলে তুমি কখনোই Performance Optimization করতে পারবে না।

⭐ ১. The Paradox: Single Threaded কিন্তু Async?

কল্পনা করো একটি রেস্টুরেন্টের কথা:

🍽️ Waiter (JS Call Stack):

রেস্টুরেন্টে মাত্র একজন ওয়েটার আছে। সে একবারে এক টেবিলের অর্ডারই নিতে পারে।

🍳 Kitchen (Web APIs):

রান্নাঘর, যেখানে আসল কাজ (রান্না) হয়। এখানে অনেক শেফ আছে।

⛔ Synchronous (Blocking):

যদি ওয়েটার কিচেনে গিয়ে দাঁড়িয়ে থাকে যতক্ষণ না রান্না শেষ হচ্ছে, তবে সে অন্য টেবিলের অর্ডার নিতে পারবে না। পুরো রেস্টুরেন্ট অচল হয়ে যাবে। উদাহরণ: alert('Hello') দিলে ব্রাউজারে আর কিছু ক্লিক করা যায় না।

✅ Asynchronous (Non-Blocking):

ওয়েটার অর্ডার নিয়ে কিচেনে স্লিপ ধরিয়ে দিয়ে সাথে সাথে অন্য টেবিলের অর্ডার নিতে চলে আসে। রান্না শেষ হলে কিচেন থেকে বেল বাজানো হয় (Callback), তখন ওয়েটার খাবার সার্ভ করে।

Senior Insight:

জাভাস্ক্রিপ্ট ইঞ্জিন (V8) একা সব কাজ করে না। ভারী কাজগুলো (Network Request, Timer) সে Browser (Web APIs) এর ঘাড়ে চাপিয়ে দেয়।

⭐ ২. আর্কিটেকচার: কে কী কাজ করে?

জাভাস্ক্রিপ্ট রানটাইম মূলত ৪টি অংশ নিয়ে গঠিত:

📚 Call Stack:

যেখানে কোড এক্সিকিউট হয় (ওয়েটার)

🌐 Web APIs:

ব্রাউজারের ফিচার (setTimeout, Fetch, DOM)। এরা ব্যাকগ্রাউন্ডে কাজ করে (কিচেন)

📋 Task Queues:

কাজ শেষ হওয়ার পর রেজাল্ট এখানে এসে জমা হয় (সার্ভিং কাউন্টার)

🔄 Event Loop:

সেই ট্রাফিক পুলিশ বা ম্যানেজার, যে সিদ্ধান্ত নেয় কখন কিউ থেকে স্ট্যাকে ডেটা পাঠাবে

⭐ ৩. Sync vs Async Code (Visualized)

🔄 Synchronous Code

console.log("1. Start");
console.log("2. Process");
console.log("3. End");

// Output: 1 -> 2 -> 3 (সহজ হিসাব)

⏳ Asynchronous Code

console.log("1. Start");

setTimeout(() => {
    console.log("2. Timer Done");
}, 2000);

console.log("3. End");

// Output:
// Start
// End
// Timer Done

কেন? কারণ setTimeout দেখার সাথে সাথেই JS সেটাকে Web API এর কাছে পাঠিয়ে দেয় এবং পরের লাইনে চলে যায়। ২ সেকেন্ড পর API সেটাকে কিউ-তে ফেরত পাঠায়।

⭐ ৪. The Event Loop: ট্রাফিক পুলিশ 🚦

ইভেন্ট লুপের কাজ মাত্র একটি এবং অত্যন্ত সহজ:

Event Loop-এর অ্যালগরিদম:

  1. Call Stack কি খালি?
  2. যদি খালি হয়, তবে Queue-তে কোনো কাজ আছে কি?
  3. যদি থাকে, তবে Queue-এর প্রথম কাজটা তুলে Stack-এ পাঠিয়ে দাও

এজন্যই ২ সেকেন্ডের টাইমার ৩ সেকেন্ডও লাগতে পারে, যদি স্ট্যাক খালি না থাকে!

⭐ ৫. VIP vs Common: Microtask vs Task Queue (Senior Concept) 🚨

সব টাস্ক সমান নয়। ইভেন্ট লুপের কাছে দুই ধরনের কিউ থাকে:

⭐ Microtask Queue (VIP Lane):

কে থাকে? Promise.then, catch, queueMicrotask, MutationObserver

Priority: সবার আগে। Call Stack খালি হলেই ইভেন্ট লুপ আগে এখানে চেক করে।

📋 Task Queue / Macrotask Queue (Regular Lane):

কে থাকে? setTimeout, setInterval, DOM Events

Priority: Microtask এর পরে

🔥 The Famous Interview Code

আউটপুট কী হবে বলো তো?

console.log("1");

setTimeout(() => console.log("2"), 0);

Promise.resolve().then(() => console.log("3"));

console.log("4");

Output & Logic:

1 (Sync - সরাসরি স্ট্যাকে)

4 (Sync - সরাসরি স্ট্যাকে)

3 (Microtask - স্ট্যাক খালি হলে VIP রা আগে যাবে)

2 (Macrotask - সবার শেষে রেগুলার কাজ)

Result: 1 -> 4 -> 3 -> 2

⭐ ৬. Callback Hell (The Pyramid of Doom) 💀

যখন একটার ভেতর আরেকটা এসিঙ্ক কাজ করতে হয়, তখন কোড পিরামিডের মতো হয়ে যায়।

// ❌ Bad Code (Callback Hell)
getUser(101, function(user) {
    getPosts(user.id, function(posts) {
        getComments(posts[0].id, function(comments) {
            console.log("Finally got comments:", comments);
        });
    });
});

সমস্যা:

  • পড়া অসম্ভব
  • এরর হ্যান্ডেল করা কঠিন
  • ডিবাগিং দুঃস্বপ্ন

সমাধান: Promise এবং Async/Await (যা আমরা অধ্যায় ৯ ও ১০-এ শিখব)

⭐ ৭. Real-Life Async: Fetch API

console.log("Start Request");

fetch("https://api.github.com/users/shagor")
    .then(response => response.json()) // Microtask
    .then(data => console.log(data.name)); // Microtask

console.log("End Script");

Flow:

  1. "Start Request" প্রিন্ট হবে
  2. fetch রিকোয়েস্ট পাঠাবে এবং ব্যাকগ্রাউন্ডে চলে যাবে
  3. "End Script" প্রিন্ট হবে
  4. ডেটা আসলে then এর কাজ Microtask Queue তে জমা হবে
  5. স্ট্যাক খালি হলে ডেটা প্রিন্ট হবে

🧠 ৮. Senior Level Interview Questions

Q1: setTimeout(fn, 0) দিলেই কি সাথে সাথে রান হবে?

উত্তর: না! "0" মানে মিনিমাম ০ মিলিসেকেন্ড অপেক্ষা। কিন্তু যতক্ষণ Call Stack খালি না হচ্ছে, ততক্ষণ ইভেন্ট লুপ এটাকে রান করবে না। যদি স্ট্যাকে বড় কোনো লুপ চলে, তবে ০ সেকেন্ডের টাইমার ১০ সেকেন্ড পরেও রান হতে পারে।

Q2: Microtask Queue যদি খালি না হয় তবে কী হবে?

উত্তর: একে বলা হয় "Starvation"। যদি তুমি একটার পর একটা প্রমিস চেইন করতে থাকো, তবে ইভেন্ট লুপ কখনোই Macrotask (যেমন: ক্লিক ইভেন্ট বা setTimeout) এর দিকে তাকাবে না। ব্রাউজার হ্যাং হয়ে যাবে।

Q3: JavaScript কি মাল্টি-থ্রেডিং সাপোর্ট করে?

উত্তর: JS মেইন থ্রেডে সিঙ্গেল থ্রেডেড। কিন্তু Web Workers ব্যবহার করে আমরা মাল্টি-থ্রেডিংয়ের মতো আচরণ তৈরি করতে পারি (তবে সেটা ভিন্ন টপিক)।

🚀 অধ্যায় ৮ সারাংশ (Checklist)

আমরা শিখলাম:

  • Architecture: JS ইঞ্জিন + Web APIs + Queue + Event Loop
  • Hierarchy: Stack > Microtask (Promise) > Macrotask (setTimeout)
  • Non-blocking: ভারী কাজ ব্রাউজারের ওপর ছেড়ে দিয়ে JS ফ্রি থাকে
  • Callback Hell: নেস্টেড কলব্যাক কেন খারাপ
  • Event Loop: স্ট্যাক খালি হওয়ার অপেক্ষায় থাকা প্রহরী

Next Step: Callback Hell থেকে মুক্তি পাওয়ার জন্য ES6 আমাদের দিয়েছে Promises। এটি অ্যাসিনক্রোনাস কোডের গেম চেঞ্জার। পরের অধ্যায়: "Promises — From Callback Hell to Heaven"।

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।