Promise vs Async/Await
Understanding Promises and Async/Await in JavaScript with examples.
Promise vs Async/Await
In JavaScript, Promise and Async/Await are two methods used to handle asynchronous operations. Both solve the same problem but follow different approaches.
Synchronous Programming
+-------------------+ +---------------------+ +-------------------+
| Task 1 Starts | ----> | Task 1 Completes | ----> | Task 2 Starts |
+-------------------+ +---------------------+ +-------------------+
Asynchronous Programming
+-------------------+ +-------------------+
| Task 1 Starts | ----> | Task 2 Starts |
+-------------------+ +-------------------+
| |
v v
+---------------------+ +---------------------+
| Task 1 Completes | | Task 2 Completes |
+---------------------+ +---------------------+
What is Asynchronous Programming?
Unlike synchronous programming, where each task must complete before the next one starts, asynchronous programming allows multiple tasks to run independently.
This helps JavaScript remain responsive while waiting for operations like:
- API requests
- Database calls
- File operations
- Timers
In asynchronous programming:
- The program does not wait for a task to finish
- It continues executing other tasks
- Results are handled later when available
1) Promise
A Promise in JavaScript represents a value that may be available:
- now
- in the future
- or never
Promises are used to handle future asynchronous results.
Promise States
A Promise has 3 states:
- Pending → Initial state
- Fulfilled / Resolved → Operation completed successfully
- Rejected → Operation failed
Initially, every Promise starts in the pending state.
Handling a Promise
Promises are handled using:
.then()→ Handles successful resolution.catch()→ Handles errors or rejection
Promise Example
Setup
mkdir promises
cd promises
npm init -y
npm i node-fetch
app.js
const fetch = require("node-fetch");
function apiFetch() {
const data = new Promise((resolve, reject) => {
fetch("<URL>", {
method: "GET",
})
.then((res) => res.json())
.then((data) => resolve(data))
.catch((err) => reject(err));
});
data
.then((res) => console.log(res))
.catch((err) => console.log(err));
}
console.log("Fetching...");
apiFetch();
console.log("Fetched...");
Output
Fetching...
Fetched...
[{ <data> }]
You may notice that "Fetched..." appears before the API response.
This happens because Promises are non-blocking. JavaScript continues executing the remaining code while the API request runs in the background.
Code Explanation
Creating a Promise
new Promise((resolve, reject) => {})
resolve()→ Marks the Promise as successfulreject()→ Marks the Promise as failed
fetch() Returns a Promise
fetch("<URL>")
The fetch() method itself returns a Promise.
Why Another .then()?
.then((res) => res.json())
res.json() also returns a Promise.
So we use another .then() to resolve the JSON data.
Important Note
Without handling the Promise properly, you may see:
Promise { <pending> }
instead of actual data.
Simple Analogy
Think of a Promise like ordering food at a restaurant.
- You place the order
- The kitchen prepares it
- Meanwhile, you continue talking with friends
- Once ready, the food is delivered
Similarly:
resolve()→ Food delivered successfullyreject()→ Something went wrong
2) Async/Await
async/await is another way to handle asynchronous operations.
It is built on top of Promises and provides cleaner, more readable syntax.
Key Points
- An
asyncfunction always returns a Promise awaitpauses execution until the Promise resolves- Makes asynchronous code look synchronous
Async/Await Example
async function fetchData() {
try {
console.log("Fetching...");
const data = await fetch("<URL>", {
method: "GET",
});
const res = await data.json();
console.log(res);
console.log("Fetched...");
} catch (error) {
console.log(error);
}
}
fetchData();
Output
Fetching...
[{ <data> }]
Fetched...
Explanation
async Function
async function fetchData() {}
This tells JavaScript the function contains asynchronous operations.
await Keyword
const data = await fetch(...)
await pauses execution until the Promise resolves.
Unlike standard Promise chaining, the code waits here before moving to the next line.
Why await data.json()?
const res = await data.json();
Because data.json() also returns a Promise.
Using await resolves it into actual JSON data.
Error Handling
Always use try...catch with async/await:
try {
// async code
} catch (error) {
console.log(error);
}
This helps handle rejected Promises cleanly.
Promise vs Async/Await
| Promise | Async/Await |
|---|---|
Uses .then() and .catch() | Uses async and await |
| Chain-based syntax | Cleaner syntax |
| Can become harder to read | Easier to understand |
| Non-blocking flow | Looks synchronous |
| Better for complex chaining | Better for readability |
Conclusion
Both Promises and Async/Await are used to handle asynchronous operations in JavaScript.
Promise Analogy
A Promise is like receiving a restaurant token:
- You continue doing other things
- Later, your food arrives
Async/Await Analogy
Async/Await is like cooking yourself:
- You wait until cooking finishes
- Then continue with the next step
Both approaches achieve the same goal, but async/await usually provides cleaner and more maintainable code.