🔴 HardEvent Loop Traps🐛 Debug Challenge

Generator function called synchronously inside Promise

Buggy Code — Can you spot the issue?

function* fetchUsers(ids) {
  for (const id of ids) {
    yield fetch(`/api/users/${id}`).then(r => r.json());
    // ^^^ yields a Promise, not the resolved value
  }
}

async function getAll(ids) {
  const users = [];
  for (const result of fetchUsers(ids)) {
    users.push(result); // result is a Promise, not a user!
  }
  return users; // array of Promises ❌
}

Fixed Code

// Fix 1: async generator (use for await...of)
async function* fetchUsers(ids) {
  for (const id of ids) {
    const user = await fetch(`/api/users/${id}`).then(r => r.json());
    yield user; // yield resolved value
  }
}

async function getAll(ids) {
  const users = [];
  for await (const user of fetchUsers(ids)) {
    users.push(user); // ✅ actual user objects
  }
  return users;
}

// Fix 2: parallel (faster)
async function getAllParallel(ids) {
  return Promise.all(ids.map(id =>
    fetch(`/api/users/${id}`).then(r => r.json())
  ));
}

Bug Explained

Bug: Regular generators can't await — yield hands back whatever you give it, including unresolved Promises. The consumer receives Promises, not user data.

Explanation: Regular generators are synchronous. To yield resolved async values, you need an async generator (async function*), consumed with for await...of.

Key Insight: Regular generator + async work = yields Promises. Async generator = yields resolved values. Always use async function* with for await...of for async iteration.

More Event Loop Traps Debug Challenges

🟡 MediumUI update blocked by sync code🔴 HardMicrotask starvation — UI never updates🟡 MediumsetTimeout inside a loop — all fire at once🟡 MediumMixing microtasks and DOM updates

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab