Event Loop & Deep Internals

"Inside the Engine: How JS Really Works"

জাভাস্ক্রিপ্ট সম্পর্কে দুটি কথা প্রচলিত:

  • এটি Single-Threaded (একবারে একটি কাজই করতে পারে)
  • এটি Non-Blocking (একসাথে হাজার হাজার রিকোয়েস্ট হ্যান্ডেল করতে পারে)

শুনে স্ববিরোধী মনে হচ্ছে না? এক হাতে কীভাবে দশটা কাজ করে? এই জাদুর পেছনের আর্কিটেকচারটিই হলো Event Loop। চলো আমরা V8 ইঞ্জিনের ভেতরে ঢুকে দেখি আসলে কী ঘটে।

⭐ ১. The Runtime Architecture (ম্যাপ)

জাভাস্ক্রিপ্ট রানটাইম একটি বিশাল কারখানার মতো। এর প্রধান অংশগুলো হলো:

  • Memory Heap (The Warehouse): মেমোরি এলোকেশন এরিয়া। আমরা যখন const user = { name: "Shagor" } লিখি, তখন এই অবজেক্টটা হিপ (Heap)-এ জায়গা নেয়। এটি একটি বিশাল, অগোছালো স্টোরেজ।
  • Call Stack (The Workbench): এক্সিকিউশন এরিয়া। ফাংশনগুলো এখানে একটার পর একটা রান হয়।
  • Web APIs (The Helpers): ব্রাউজারের ফিচার (DOM, AJAX, Timeout)। এরা JS ইঞ্জিনের অংশ নয়, কিন্তু JS এদের ব্যবহার করে।
  • Queues (The Waiting Rooms): কাজ শেষ হলে কলব্যাক ফাংশনগুলো এখানে এসে অপেক্ষা করে।
  • Event Loop (The Manager): যে সিদ্ধান্ত নেয় কখন কাকে স্ট্যাকে পাঠাবে।

⭐ ২. Call Stack: কাজের সিরিয়াল খাতা 📝

এটি LIFO (Last In, First Out) মেথডে কাজ করে।

function multiply(x, y) {
    return x * y;
}
function printSquare(n) {
    const res = multiply(n, n);
    console.log(res);
}
printSquare(5);

Stack Flow:

  • GEC (Global Execution Context) তৈরি হয়
  • printSquare(5) স্ট্যাকে ঢোকে
  • এর ভেতর multiply(5, 5) কল হয় → এটি স্ট্যাকে printSquare এর ওপরে বসে
  • multiply রিটার্ন করে → স্ট্যাক থেকে বের হয়ে যায় (Pop)
  • console.log স্ট্যাকে আসে এবং প্রিন্ট করে বের হয়ে যায়
  • printSquare বের হয়ে যায়
  • স্ট্যাক খালি

⭐ ৩. Web APIs & The Need for Async

যদি JS সব কাজ একা করত, তবে setTimeout দিলে ৫ সেকেন্ডের জন্য পুরো ওয়েবসাইট হ্যাং হয়ে যেত (Blocking)।

তাই, যখনই কোনো ভারী কাজ আসে (Timer, API Call), জাভাস্ক্রিপ্ট সেটা Web API (ব্রাউজারের ব্যাকগ্রাউন্ড থ্রেড)-এর কাছে পাঠিয়ে দেয় এবং নিজে পরের লাইনে চলে যায়।

⭐ ৪. The Battle of Queues: Microtask vs Macrotask ⚔️

এখানেই ৯৯% জুনিয়র ডেভেলপার ভুল করে। সব কিউ সমান নয়। ইভেন্ট লুপের কাছে দুই ধরণের লাইন থাকে:

A. Microtask Queue (VIP 👑)

এদের প্রায়োরিটি সবার আগে। স্ট্যাক খালি হওয়ার সাথে সাথে ইভেন্ট লুপ আগে এখানে চেক করে।

সদস্য: Promise (.then/catch/finally), queueMicrotask, MutationObserver

B. Macrotask Queue (Common Public 🚶)

এরা সাধারণ টাস্ক। Microtask Queue পুরো খালি হলে তবেই ইভেন্ট লুপ এদের দিকে তাকায়।

সদস্য: setTimeout, setInterval, I/O, setImmediate (Node)

Golden Rule:

প্রতিটি Macrotask রান করার পর, ইভেন্ট লুপ চেক করে কোনো Microtask বাকি আছে কিনা। যদি থাকে, তবে সবগুলো Microtask শেষ না করা পর্যন্ত সে অন্য কিছু ধরবে না।

⭐ ৫. The Event Loop Algorithm (Deep Steps) 🔄

ইভেন্ট লুপ আসলে একটা ইনফিনিট লুপ যা সবসময় নিচের ধাপগুলো চেক করে:

  1. Check Call Stack: স্ট্যাক কি খালি? (না হলে অপেক্ষা করো)
  2. Process Microtasks: স্ট্যাক খালি হলে, Microtask Queue তে যা আছে সব শেষ করো
  3. Render UI: ব্রাউজারের যদি রি-পেইন্ট (Repaint) করার দরকার হয়, করো
  4. Process ONE Macrotask: এবার Macrotask Queue থেকে মাত্র ১টি টাস্ক নিয়ে স্ট্যাকে পাঠাও
  5. আবার ১ নম্বরে যাও

⭐ ৬. Visual Challenge: Mind-Blowing Example 🔥

console.log("1. Start");

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

Promise.resolve()
  .then(() => {
    console.log("3. Promise 1");
    return Promise.resolve(); // নতুন প্রমিজ রিটার্ন
  })
  .then(() => console.log("4. Promise 2"));

console.log("5. End");

Execution Flow:

  1. log("1. Start") ➡ প্রিন্ট "1. Start"
  2. setTimeout ➡ Web API তে গেল → Macrotask Queue-তে
  3. Promise ➡ Microtask Queue-তে
  4. log("5. End") ➡ প্রিন্ট "5. End"
  5. Microtask-এ first then ➡ প্রিন্ট "3. Promise 1" → নতুন Promise Microtask-এ
  6. Microtask-এ Promise 2 ➡ প্রিন্ট "4. Promise 2"
  7. Macrotask-এ Timeout ➡ প্রিন্ট "2. Timeout"

Final Output: 1. Start → 5. End → 3. Promise 1 → 4. Promise 2 → 2. Timeout

⭐ ৭. queueMicrotask() & UI Blocking (Performance Trap) ⚠️

VIP বানানো:

queueMicrotask(() => console.log("I am VIP"));
setTimeout(() => console.log("I am Common"), 0);

বিপদ (UI Blocking):

যেহেতু ইভেন্ট লুপ Microtask শেষ না হওয়া পর্যন্ত রেন্ডারিং বা অন্য কাজ ধরে না, তাই তুমি যদি ইনফিনিট লুপে প্রমিজ বানাতে থাকো, ব্রাউজার হ্যাং হয়ে যাবে।

function heavy() {
    queueMicrotask(heavy); // নিজেকেই বারবার কল করছে (Recursive Microtask)
}
// heavy(); // ❌ চালালে ট্যাব ক্র্যাশ করবে! মাউস নড়বে না।

কিন্তু setTimeout রিকার্সিভলি কল করলে ব্রাউজার হ্যাং হয় না, কারণ প্রতিবার কল করার মাঝখানে ইভেন্ট লুপ রেন্ডারিং করার সুযোগ পায়।

⭐ ৮. Web Workers: The Real Multithreading

যেহেতু JS মেইন থ্রেডে চলে, তাই ভারী ক্যালকুলেশন (যেমন ইমেজ প্রসেসিং) করলে UI আটকে যায়। এর সমাধান Web Workers। এটি মেইন থ্রেডের বাইরে আলাদা একটি থ্রেডে কাজ করে।

// main.js
const worker = new Worker("heavy-task.js");
worker.postMessage("Start"); // কাজ পাঠালাম

worker.onmessage = function(e) {
    console.log("Result form Worker:", e.data); // রেজাল্ট পেলাম
};

⭐ ৯. Node.js Event Loop (Differences) 🟢

Node.js এবং ব্রাউজারের ইভেন্ট লুপ ৯০% এক, তবে কিছু পার্থক্য আছে। নোডের ইভেন্ট লুপে ৬টি ফেজ (Phase) থাকে:

  • Timers: setTimeout, setInterval
  • Pending Callbacks: System operations (like TCP errors)
  • Idle, Prepare: Internal use
  • Poll: I/O operations (file reading, network)
  • Check: setImmediate
  • Close Callbacks: socket.on('close')

Note: Node.js এ process.nextTick() নামে আরেকটি কিউ আছে যা Microtask-এর চেয়েও বেশি প্রায়োরিটি পায়।

🧠 ১০. Senior Level Interview Questions

Q1: setTimeout এর সময় ০ দিলেও কেন দেরি হয়?

উত্তর: কারণ "০" মানে "এখনই রান করো" না। এর মানে "মিনিমাম ০ সেকেন্ড অপেক্ষা করো"। কল স্ট্যাক খালি না হওয়া পর্যন্ত এবং সব Microtask শেষ না হওয়া পর্যন্ত এটি রান হবে না।

Q2: Event Loop কি জাভাস্ক্রিপ্ট ইঞ্জিনের অংশ?

উত্তর: টেকনিক্যালি না! V8 ইঞ্জিন শুধু কোড এক্সিকিউট করে (Call Stack & Heap)। Event Loop, Web APIs এবং Callback Queue ব্রাউজার বা Node.js রানটাইম এনভায়রনমেন্ট প্রদান করে।

Q3: Promise Chain বনাম setTimeout নেস্টিং—কোনটা পারফরম্যান্সের জন্য রিস্কি?

উত্তর: Promise Chain (যদি অনেক লম্বা হয়)। কারণ এটি Microtask Queue ব্লক করে রাখে এবং UI রেন্ডারিং আটকে দেয়। setTimeout প্রতিবার ইভেন্ট লুপকে শ্বাস নেওয়ার সুযোগ দেয়।

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

আমরা শিখলাম:

  • Architecture: Call Stack (Sync), Web API (Async), Queues (Callback)
  • Hierarchy: Call Stack > Microtask (Promise) > Macrotask (Timeout)
  • Trap: Microtask শেষ না হওয়া পর্যন্ত ইভেন্ট লুপ নড়বে না (UI Block হতে পারে)
  • Node: process.nextTick সবার বস

Next Step: ইভেন্ট লুপের এই গভীর জ্ঞান নিয়ে আমরা এখন মেমোরি ম্যানেজমেন্টের দিকে যাব। কিভাবে বুঝবে অ্যাপে মেমোরি লিক হচ্ছে? গার্বেজ কালেকশন কিভাবে কাজ করে? পরের অধ্যায়: "Advanced Data Structures (Map, Set, WeakMap)" এবং "Memory Management"।

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

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