Topic 06 / 10

Asynchronous JS, Event Loop, Promises & async/await

1. Simple Definition

JavaScript ek Single-Threaded language hai — iska matlab iske paas sirf ek hi Call Stack hota hai aur ye ek time par sirf ek hi line of code execute kar sakti hai. Lekin agar hume internet se 2 second lagakar data mangwana ho, toh kya browser 2 second ke liye freeze ho jayega? Nahi! Browser ke Asynchronous Architecture (Web APIs + Event Loop) ki wajah se heavy tasks background me execute hote hain aur hamara main UI thread smooth chalta rehta hai.

2. Real-Life Analogy

🍔 McDonald's Buzzer Token vs Halwai Ki Dukaan

Synchronous (Halwai Ki Dukaan): Jab tak pehle customer ki jalebi tal kar pack nahi ho jati, agla customer line me wait karta hai (Blocking).
Asynchronous (McDonald's Token): Aapne Burger order kiya, counter wale ne token buzzer diya aur bola: "Aap table par aaram se baithiye, burger bante hi buzzer beep karega!" Is beech counter agle customer ka order lena shuru kar deta hai (Non-blocking).

3. Why Do We Need It?

Real-world apps me 90% operations time-consuming hote hain: database se user profile load karna, high-res image download karna, timer chalana, ya payment gateway response ka wait karna. Agar JS synchronous hoti, toh har network request ke dauran browser screen freeze (not responding) ho jati.

4. Syntax & Evolution: Callbacks to async/await

// 1. Purana Tareeka: Callback Hell (Pyramid of Doom)
getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      console.log("Too many nested brackets!");
    });
  });
});

// 2. ES6: Promises (.then / .catch)
const fetchUser = () => {
  return new Promise((resolve, reject) => {
    let success = true;
    setTimeout(() => {
      if (success) resolve({ name: "Rahul", role: "Dev" });
      else reject("Error loading user");
    }, 1000);
  });
};

fetchUser()
  .then(user => console.log("User:", user.name))
  .catch(err => console.error("Failed:", err));

// 3. Modern Standard: async / await (Clean & Synchronous-Looking)
async function displayUser() {
  try {
    const user = await fetchUser();
    console.log("Async User:", user.name);
  } catch (error) {
    console.error("Caught error:", error);
  } finally {
    console.log("Done loading spinner stop!");
  }
}
displayUser();

5. Basic Example: Custom Sleep Helper with Promises

// Modern Promisified delay helper
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

async function runCountdown() {
  console.log("Starting countdown...");
  await delay(1000);
  console.log("3...");
  await delay(1000);
  console.log("2...");
  await delay(1000);
  console.log("1...");
  await delay(1000);
  console.log("🚀 Rocket Launched!");
}

runCountdown();

6. Output & Interactive Event Loop Demonstration

Interactive Execution Order Test

Guess karein console me pehle kya print hoga: 1, 2, 3 ya 4?

7. Code Explanation: Event Loop Architecture

Component Kaam (Role) Example Operations
Call Stack Code ko line-by-line execute karna (LIFO - Last In First Out). Variable assignment, loops, normal function calls.
Web APIs Browser ke background helper engines jo timers aur network calls sambhalte hain. setTimeout(), fetch(), addEventListener().
Microtask Queue VIP High Priority! Call stack khali hote hi pehle iski execution hoti hai. Promise.then(), async/await resume, queueMicrotask().
Callback Queue (Macrotask) Normal priority queue jo Microtask queue khali hone ke baad execute hoti hai. setTimeout() callbacks, setInterval, UI click events.
Event Loop Continuous traffic policeman: Stack empty hote hi Queue se items Stack me bhejna. Infinite loop running inside browser engine.

8. Real-World Example: Parallel Requests with Promise.all

// Dono API calls ek saath parallel me start hongi (Time bachega!)
async function loadDashboard() {
  try {
    const [userData, ordersData] = await Promise.all([
      fetch('/api/user/101').then(res => res.json()),
      fetch('/api/user/101/orders').then(res => res.json())
    ]);

    console.log("User Name:", userData.name);
    console.log("Total Orders:", ordersData.length);
  } catch (err) {
    console.error("Koi ek API request fail ho gayi:", err);
  }
}

9. Common Mistakes

⚠️ Forgetting 'await' = [object Promise]

Agar aap likhte hain: const user = fetchUser(); console.log(user.name); toh user.name undefined aayega! Kyunki user abhi data nahi balki ek Promise { <pending> } hai. Data access karne ke liye await fetchUser() likhna mandatory hai.

10. Best Practices

  • Hamesha async function ke andar try...catch lagayein taaki unhandled promise rejection error se browser console lal na ho.
  • Agar multiple API calls ek doosre par depend nahi karti, toh unhe sequentially await a; await b; karne ke bajaye Promise.all() se parallel call karein.
  • Agar aap chahte hain ki ek request fail hone par bhi baaki chalte rahein, toh Promise.allSettled() use karein.

11. Try It Yourself

Code Playground me Promise.race() test karein: Do promises banayein (ek 500ms delay aur doosri 1000ms delay), aur dekhein ki kaunsi race jeetti hai!

12. Challenge

Ek function banayein fetchWithTimeout(url, timeoutMs) jo agar server se 3 second me response na aaye toh automatically request abort karke "Timeout Error: Server slow hai!" reject kare.

13. Interview Questions

💼 Q1: Microtask Queue aur Macrotask Queue me kya farq hai? Kaun pehle chalega?

Answer: Microtask queue (Promises, async/await, mutation observer) ki priority Macrotask queue (setTimeout, setInterval) se zyada hoti hai. Jab Call Stack empty hota hai, Event Loop pehle Microtask queue ke sabhi tasks execute karta hai, uske baad hi setTimeout ka callback run hota hai.

💼 Q2: Promise ke 3 states kaunse hote hain?

Answer: 1. Pending: Kaam abhi chal raha hai. 2. Fulfilled (Resolved): Kaam successfully pura ho gaya. 3. Rejected: Error ya network failure ho gaya.

14. Quick Revision

  • JS is single-threaded; Event loop makes it non-blocking.
  • Promises represent future values (Pending, Resolved, Rejected).
  • async makes a function return a Promise; await pauses until resolved.
  • Microtasks (Promises) > Macrotasks (setTimeout).

15. FAQ

Q1. Kya async/await multithreading create karta hai?

Nahi! Ye syntax sirf syntactic sugar hai Promises ke upar. Thread wahi single rehta hai.

Q2. Real multithreading JS me kaise hoti hai?

Browser me Web Workers API ke through background threads create kiye ja sakte hain jo heavy calculations karte hain.

Q3. setTimeout(fn, 0) ka matlab immediate execution hota hai?

Nahi! Iska matlab hai: "Call stack khali hone aur saare microtasks nipatne ke baad turant run karo".

Q4. Promise.race() kab use karte hain?

Jab aap fastest server mirror se data load karna chahte hain ya network timeout implement karna chahte hain.

Q5. Agar catch block na lagayein toh kya hoga?

Browser console me Uncaught (in promise) error aayega jo production me application crash kar sakta hai.

Topic 06 / 10

Asynchronous JS, Event Loop, Promises & async/await

1. Simple Definition

JavaScript is a single-threaded programming language, meaning it can only execute one command at a time. To prevent long-running tasks (like network API requests or file downloads) from freezing the user interface, JavaScript employs an Asynchronous Event Loop architecture powered by Promises and async / await.

2. Real-Life Analogy

🍔 Fast Food Restaurant Buzzer Token

You place an order for a burger at the counter. The cashier does not make you stand in front of the cash register for 10 minutes freezing the entire queue! Instead, they hand you an electronic vibrating buzzer (a Promise). You sit down and check your phone (browser stays responsive). When the food is ready, the buzzer vibrates (Promise resolves) and you collect your meal!

3. The Event Loop Architecture

The JavaScript runtime coordinates between:

  • Call Stack: Executes synchronous code one frame at a time.
  • Web APIs: Background browser threads handling timers (setTimeout), DOM events, and network fetches.
  • Microtask Queue: High-priority queue for Promise resolutions (.then(), await).
  • Task Queue (Macrotasks): Standard queue for setTimeout and setInterval callbacks.

4. Promises: States & Syntax

// A Promise has 3 states: Pending -> Fulfilled OR Rejected
const orderBurger = new Promise((resolve, reject) => {
  const isAvailable = true;
  setTimeout(() => {
    if (isAvailable) resolve("🍔 Burger is ready!");
    else reject(new Error("Out of stock!"));
  }, 1000);
});

// Consuming Promise via .then() and .catch()
orderBurger
  .then(meal => console.log(meal))
  .catch(err => console.error(err.message));

5. Modern async / await (Syntactic Sugar)

// async functions return a Promise automatically
async function fetchUserDashboard(userId) {
  try {
    console.log("Loading dashboard...");
    const response = await fetch(`https://api.example.com/users/${userId}`);
    if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);

    const userData = await response.json();
    return userData;
  } catch (error) {
    console.error("Dashboard failed to load:", error.message);
    return null;
  }
}

6. Common Mistakes

⚠️ Common Pitfall: Forgetting await on response.json()

Both fetch() and response.json() return Promises! If you write const data = response.json(); without await, data becomes a pending Promise object instead of the actual data payload!

7. Best Practices

  • Always use async / await over deeply chained .then() callbacks.
  • Always wrap await statements in try / catch blocks.
  • Use Promise.all() to fire multiple independent network requests concurrently!

8. Practice Exercise

🎯 Exercise: Parallel Data Fetching

Fetch user profile and user posts simultaneously using Promise.all([fetchUser(), fetchPosts()]) and log the combined results.

9. Interview Questions

💼 Q: What is the execution order between Microtasks and Macrotasks?

Answer: The Call Stack executes all synchronous code first. Once empty, the Event Loop drains the entire Microtask Queue (Promises) completely before processing the next Macrotask (setTimeout/setInterval).

10. Summary / Cheat Card

  • JavaScript is single-threaded; Event Loop handles concurrency.
  • Promises represent future values (Pending, Fulfilled, Rejected).
  • async / await makes asynchronous code read like synchronous logic.
  • Promise.all() executes parallel requests concurrently.

11. FAQ

Q1. What is Promise.allSettled()?

Unlike Promise.all() which fails fast if any promise rejects, Promise.allSettled() waits for all promises to finish regardless of success or failure.