Loading...
Loading...
Why JavaScript doesn't wait — and what that means for your code.
Browsers and servers spend most of their time waiting — for network responses, timers, and user input. Async JavaScript lets your program stay responsive while work happens in the background using callbacks, Promises, and async/await.
Synchronous code runs line-by-line and blocks until each step finishes; asynchronous code starts work and continues later via callbacks and the event loop. See why blocking the thread breaks user experience.
Synchronous code runs one line at a time. But real applications wait for network requests, file reads, and timers. Async JavaScript lets your program keep running while that work happens in the background — without freezing the UI.
This module covers the full async story: callbacks, Promises, async/await, and the Fetch API. Visual timelines show when tasks enter the queue, when they resolve, and why async/await is syntactic sugar over Promises — not magic.
Every network request, timer, and file read is async. Choosing sync versus async shapes architecture, error handling, and whether your app feels instant or frozen — it is the gateway to promises and async/await.
Runs line by line. Each line waits for the previous one to finish.
console.log("First"); // 1️⃣ runs console.log("Second"); // 2️⃣ waits, then runs console.log("Third"); // 3️⃣ waits, then runs // Output (always in order): // "First" // "Second" // "Third"
Synchronous = sequential. Line 2 can't start until line 1 finishes. Predictable, ordered execution.
What happens when synchronous code takes too long?
// Imagine fetching data synchronously (DON'T do this): const data = fetchFromServer(); // ⏳ 3 seconds... // NOTHING happens for 3 seconds: // - Page freezes // - Buttons don't respond // - Animations stop // - User thinks it's broken console.log(data); // finally runs after 3s
Why this is a problem:
Starts a task, moves on, comes back when it's done.
console.log("First"); // 1️⃣ runs immediately setTimeout(() => { console.log("Second"); // 3️⃣ runs LATER (after 1s) }, 1000); console.log("Third"); // 2️⃣ runs immediately! // Output: // "First" // "Third" ← doesn't wait! // "Second" ← runs after 1 second
Async code doesn't block. setTimeout schedules work for later and immediately moves to the next line.
Synchronous vs Asynchronous:
SYNC
→ task 1 (wait...)
→ task 2 (wait...)
→ task 3 (wait...)
total: sum of all
ASYNC
→ start task 1
→ start task 2
→ start task 3
total: longest one
How JavaScript handles async — the big picture.
// The Event Loop cycle: // 1. Run all synchronous code (call stack) // 2. Check if any async tasks are done // 3. Run their callbacks // 4. Repeat console.log("A"); // 1. call stack setTimeout(() => { console.log("B"); // 3. callback queue (after 0ms!) }, 0); console.log("C"); // 2. call stack // Output: A, C, B // Even with 0ms delay, setTimeout waits for // synchronous code to finish first!
💡 The event loop ensures async callbacks only run after the current synchronous code finishes. This is why setTimeout(fn, 0) doesn't run immediately.
The main ways to write asynchronous JavaScript.
// 1. Callbacks (oldest pattern): fetchData(url, function(data) { process(data); }); // 2. Promises (ES6): fetchData(url) .then(data => process(data)) .catch(err => handle(err)); // 3. Async/Await (ES2017 — cleanest): async function load() { try { const data = await fetchData(url); process(data); } catch (err) { handle(err); } }
We'll cover each pattern in depth in the following chapters. They all solve the same problem — handling operations that take time.
Common questions about sync vs async.