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.