Episode 1 — Fundamentals / 1.17 — Asynchronous Programming JavaScript
1.17 — Exercise Questions: Asynchronous Programming
Practice questions for all five subtopics in Section 1.17. Mix of conceptual, code prediction ("what does this output?"), write-the-code, and debugging exercises.
How to use this material (instructions)
- Read lessons in order —
README.md, then1.17.a→1.17.e. - Answer closed-book first — then compare to the matching lesson.
- Run code — paste prediction questions into the browser Console or Node.js to verify.
- Interview prep —
1.17-Interview-Questions.md. - Quick review —
1.17-Quick-Revision.md.
1.17.a — Introduction to Asynchrony (Q1–Q10)
Q1. Define synchronous and asynchronous execution in one sentence each.
Q2. Why can't JavaScript simply run long operations synchronously in the browser?
Q3. Name the three key components of the event loop mechanism.
Q4. What is the difference between the microtask queue and the macrotask queue? Give one example of each.
Q5. Code prediction: What is the output?
console.log("A");
setTimeout(() => console.log("B"), 0);
Promise.resolve().then(() => console.log("C"));
console.log("D");
Q6. Code prediction: What is the output and why?
setTimeout(() => console.log("1"), 0);
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
Promise.resolve().then(() => console.log("4"));
console.log("5");
Q7. Explain the restaurant waiter analogy for the event loop in 3–4 sentences.
Q8. If a setTimeout is set to 100ms but a synchronous while loop runs for 500ms, when does the timer callback actually execute? Why?
Q9. True or false: Microtasks always run before macrotasks when the call stack is empty. Explain.
Q10. Draw (or describe in text) the path a setTimeout callback takes from registration to execution, mentioning: call stack, Web API, macrotask queue, event loop.
1.17.b — Callbacks and Callback Problems (Q11–Q22)
Q11. What is a callback function? Write a simple example.
Q12. Is Array.prototype.map a synchronous or asynchronous callback? How do you know?
Q13. Code prediction: What is the output?
console.log("Start");
[1, 2, 3].forEach(n => console.log(n));
console.log("End");
Q14. Code prediction: What is the output?
console.log("Start");
setTimeout(() => console.log("Timeout"), 0);
[1, 2, 3].forEach(n => console.log(n));
console.log("End");
Q15. Explain the error-first callback pattern. Write a function divide(a, b, callback) that uses this pattern (error if b is 0).
Q16. Rewrite this callback hell into flattened named functions:
getUser(1, (err, user) => {
getPosts(user.id, (err, posts) => {
getComments(posts[0].id, (err, comments) => {
console.log(comments);
});
});
});
Q17. What is inversion of control in the context of callbacks? Name two risks.
Q18. Why doesn't the named-function approach fully solve callback problems?
Q19. Debugging: This code is supposed to print the user name but prints undefined. Find the bug.
function getUser(id, callback) {
setTimeout(() => {
callback({ id: id, name: "Alice" });
}, 100);
}
const result = getUser(1, user => user.name);
console.log(result);
Q20. Write an error-first callback version of a function readConfig(path, callback) that returns {error: null, data: "config"} if path is "config.json" and an error otherwise. Use setTimeout to simulate async.
Q21. True or false: All callbacks are asynchronous. Explain.
Q22. List three limitations of callbacks that Promises address.
1.17.c — Understanding Promises (Q23–Q36)
Q23. Name the three states of a Promise. Can a Promise transition from fulfilled back to pending?
Q24. Create a Promise that resolves with "Hello" after 1 second.
Q25. Code prediction: What is the output?
const p = new Promise((resolve, reject) => {
resolve("first");
resolve("second");
reject("error");
});
p.then(val => console.log(val));
p.catch(err => console.log(err));
Q26. Code prediction: What is the output?
Promise.resolve(1)
.then(x => x + 1)
.then(x => { throw new Error("fail"); })
.then(x => console.log("A:", x))
.catch(err => console.log("B:", err.message))
.then(() => console.log("C"));
Q27. What happens if you forget to return inside a .then() callback? Write an example showing the problem.
Q28. Convert this callback-based function to return a Promise:
function fetchData(url, callback) {
setTimeout(() => {
if (!url) callback(new Error("No URL"), null);
else callback(null, { data: "result" });
}, 500);
}
Q29. Explain the difference between Promise.all and Promise.allSettled with an example scenario.
Q30. Code prediction: What is the output?
const p1 = Promise.resolve("A");
const p2 = Promise.reject("B");
const p3 = Promise.resolve("C");
Promise.all([p1, p2, p3])
.then(vals => console.log("Success:", vals))
.catch(err => console.log("Error:", err));
Q31. Write code using Promise.race to implement a 3-second timeout for a fetch call.
Q32. What is the difference between Promise.race and Promise.any?
Q33. Code prediction: What is the output?
Promise.resolve("start")
.then(val => {
console.log(val);
return "middle";
})
.then(val => {
console.log(val);
// no return
})
.then(val => {
console.log(val);
});
Q34. Why is nesting .then() inside another .then() an anti-pattern? Show the correct way.
Q35. Write a chain of three .then() calls where the second throws an error. Show how .catch() handles it and the chain continues.
Q36. Exercise: Write a function retryFetch(url, attempts) that tries to fetch a URL up to attempts times before giving up. Use Promises.
1.17.d — Async/Await (Q37–Q48)
Q37. What does the async keyword do to a function's return value?
Q38. Code prediction: What is the output?
async function demo() {
return 42;
}
console.log(demo());
demo().then(val => console.log(val));
Q39. Rewrite this Promise chain using async/await:
fetch("/api/users")
.then(res => res.json())
.then(users => console.log(users))
.catch(err => console.error(err));
Q40. Why does await inside forEach not work as expected? What should you use instead for sequential processing?
Q41. Code prediction: What is the output order?
async function foo() {
console.log("A");
await Promise.resolve();
console.log("B");
}
console.log("C");
foo();
console.log("D");
Q42. Write an async function that fetches two independent APIs in parallel and returns both results.
Q43. Debugging: This code is supposed to catch the error but doesn't. Why?
async function broken() {
const data = await fetch("/nonexistent-url");
return data.json();
}
broken();
// No error caught — unhandled promise rejection
Q44. What is top-level await? In what contexts does it work?
Q45. Code prediction: What is the output?
async function slow() {
const a = await new Promise(r => setTimeout(() => r(1), 1000));
const b = await new Promise(r => setTimeout(() => r(2), 1000));
return a + b;
}
slow().then(console.log);
// How long does this take?
Q46. Rewrite the function in Q45 to run both promises in parallel. How long does it take now?
Q47. Exercise: Write an async function fetchMultipleUsers(ids) that takes an array of user IDs, fetches each user from /api/users/:id in parallel, and returns an array of user objects. Handle errors gracefully.
Q48. Explain the difference between these two:
// Version A
const result = await somePromise;
// Version B
const result = somePromise;
1.17.e — Timers (Q49–Q60)
Q49. What does setTimeout return? Why is this important?
Q50. Code prediction: What is the output?
console.log("A");
setTimeout(() => console.log("B"), 0);
console.log("C");
Q51. Write code that logs "Cancelled" immediately and cancels a timeout that would have logged "Too late" after 5 seconds.
Q52. Explain why setTimeout(fn, 100) might not fire at exactly 100ms. Name two reasons.
Q53. Code prediction: What is the output and approximate timing?
const start = Date.now();
setTimeout(() => console.log("Timer:", Date.now() - start, "ms"), 100);
// Blocking loop
let i = 0;
while (i < 1e9) { i++; }
console.log("Loop done:", Date.now() - start, "ms");
Q54. What is the drift problem with setInterval? Illustrate with an example where the callback takes 300ms and the interval is 500ms.
Q55. Write a recursive setTimeout version that guarantees a 1000ms gap between the end of one execution and the start of the next.
Q56. Exercise: Implement a simple debounce(fn, delay) function using setTimeout and clearTimeout.
Q57. Exercise: Write a countdown function that displays 10, 9, 8, ..., 1, "Go!" using recursive setTimeout.
Q58. Why is setInterval dangerous if you forget to call clearInterval? What kind of bug does this cause?
Q59. Debugging: This polling function never stops. Fix it.
async function pollStatus() {
const id = setInterval(async () => {
const res = await fetch("/api/status");
const data = await res.json();
if (data.done) {
console.log("Done!");
// Bug: how to stop?
}
}, 2000);
}
Q60. What is the difference between setTimeout(fn, 0) and queueMicrotask(fn) in terms of execution order?
Hands-on exercises
Exercise A: Event loop tracer
Predict the output of this code, then run it to verify:
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve()
.then(() => {
console.log("3");
setTimeout(() => console.log("4"), 0);
})
.then(() => console.log("5"));
setTimeout(() => console.log("6"), 0);
console.log("7");
Exercise B: Promise chain builder
Write a function sequence(tasks) that takes an array of functions (each returning a Promise) and runs them one after another, passing each result to the next. Return a Promise with the final result.
// Example usage:
sequence([
() => Promise.resolve(1),
(prev) => Promise.resolve(prev + 10),
(prev) => Promise.resolve(prev * 2),
]).then(console.log); // 22
Exercise C: Parallel with limit
Write parallelLimit(tasks, limit) that runs at most limit tasks concurrently. Each task is a function returning a Promise. Return a Promise that resolves with an array of all results.
Exercise D: Build a stopwatch
Create a stopwatch using setInterval that displays elapsed time in the format MM:SS. Include start(), stop(), and reset() functions. Ensure no memory leaks.
Answer hints
| Q | Hint |
|---|---|
| Q5 | A, D, C, B — microtasks before macrotasks |
| Q6 | 5, 3, 4, 1, 2 — sync first, then microtasks, then macrotasks |
| Q8 | Fires at ~500ms — callback waits in queue until stack is empty |
| Q14 | Start, 1, 2, 3, End, Timeout — forEach is synchronous |
| Q19 | getUser returns undefined (no return value); the callback result is lost |
| Q25 | "first" — a Promise settles only once; second resolve and reject are ignored |
| Q26 | B: fail, then C — error caught by .catch(), chain recovers |
| Q30 | Error: B — Promise.all rejects immediately when any promise rejects |
| Q33 | start, middle, undefined — no return in second .then() |
| Q41 | C, A, D, B — await yields, D runs before B |
| Q45 | ~2 seconds (sequential awaits); Q46 version: ~1 second |
| Q50 | A, C, B — setTimeout(fn, 0) is a macrotask |
| Q53 | Loop done prints first with large ms value; timer fires after loop, well past 100ms |
| Q60 | queueMicrotask runs before setTimeout(fn, 0) |
| Ex A | 1, 7, 3, 5, 2, 6, 4 |
← Back to 1.17 — Asynchronous Programming (README)