What is it?
JavaScript is single-threaded but non-blocking. When you make a network
call, the engine doesn't wait — it parks the work and runs other code
until the result is ready. Promises and async/await are how you
express "do this when that finishes" without callback hell.
Why it matters
Almost every real frontend interaction is async: fetching data, reading files, animations, timers. Reading async code correctly — knowing when something resolves, how errors propagate, what blocks what — is the single most common source of subtle bugs.
What to learn
- The event loop: call stack, task queue, microtask queue
- Promises:
pending,fulfilled,rejected— and.then/.catch/.finally async/awaitas syntax sugar over promisesPromise.all,Promise.race,Promise.allSettled- Error propagation: thrown errors inside async functions become rejections
- Sequential vs parallel — when to
awaitin a loop and when toPromise.all
Common pitfall
Awaiting in a for loop when the calls don't depend on each other.
Sequential awaits make N requests take N × latency. Promise.all runs
them in parallel and waits for the slowest — usually 5–10× faster on
real APIs.
Resources
Primary (free):
- MDN — Using promises · docs
- JavaScript.info — Async/await · docs
- Loupe — visualize the event loop · tool
Practice
Write a function that fetches 10 user profiles from a public API. Time
two implementations: one with sequential await in a loop, one with
Promise.all. Note the difference in milliseconds. Done when you can
explain to someone else why the second is faster.
Outcomes
- Read async code and identify what runs sequentially vs concurrently.
- Choose between
Promise.alland sequentialawaitfor a real task. - Handle errors in async functions without losing the stack trace.
- Walk through the event loop for a snippet involving a timer + promise.