Async Programming
The Problem: JavaScript Is Single-Threaded
JavaScript runs on one thread — it can only do one thing at a time, processing tasks through an event loop backed by a queue. But what about tasks that take a while, like fetching data from a server, reading a file, or waiting for a timer? If JavaScript had to sit and wait for each one, your entire app would freeze.
The solution? Asynchronous programming. Instead of waiting, JavaScript says "start this task, and let me know when it's done — I'll keep doing other things in the meantime." It's like ordering food at a restaurant — you don't stand at the kitchen door waiting. You sit down, chat with friends, and the waiter brings your food when it's ready.
JavaScript's async story evolved over the years: callbacks (the old way) → Promises (the better way) → async/await (the cleanest way).
Callbacks — The Original Approach
Promises — A Better Way
A Promise is an object that represents a value that might not exist yet. Think of it like a gift card — it's a promise that you'll get something in the future. A Promise can be in one of three states:
- Pending — the operation is still running
- Fulfilled — the operation completed successfully (you can access the result)
- Rejected — the operation failed (you can access the error)
You use .then() to handle success and .catch() to handle errors. The best part? Promises can be chained, so you avoid the nested callback nightmare.
Creating & Chaining Promises
Async/Await — The Modern Way
async/await is syntactic sugar on top of Promises that makes async code look and feel like synchronous code. An async function always returns a Promise. Inside it, you can use await to pause execution until a Promise settles.
It's like turning the restaurant analogy into a story: "I await my appetizer. Then I await my main course. Then I await the bill." Each step waits for the previous one to finish, but the rest of the restaurant keeps running.
Async/Await & Fetch API
Quick check
Continue reading