Learn JavaScript asynchronous programming with callbacks, promises, and async/await. Avoid callback hell and write cleaner, maintainable code with real-world examples.
Hello my fellow frontend developers, today i will be discussing one of the most important concept in javascript, asynchronous programming.
- I'll be creating my code snippets on Scribbler.live first, which is a fantastic platform that allows you to run a JavaScript Notebook, Online Compiler, and Editor without the need for manual setup.
- Additionally, I am including a link to code snippets that includes all of the code examples so you can open the snippet and run it yourself to see the results.
- I will be using
scrib.show
from scribbler.live, it is equivalent toconsole.log
Let's dive in
Table of contents
What are callbacks?
- A callback is a function passed as an argument to another function, which is then executed later (synchronously or asynchronously).
- Callbacks are fundamental in JavaScript for handling asynchronous operations, event listeners, and functional programming.
Sample codes
Basic example
function saveOrder(orderId, userMail, callback) {
const order = {
orderId,
userMail
}
scrib.show(order)
callback(userMail); // Execute the callback function
}
function sendOrderEmail(userMail) {
scrib.show(userMail, "Order confirmed")
}
saveOrder("145908275","user@gmail.com", sendOrderEmail);
// Will log the order and sends a confirmation email to the user using sendOrderEmail
Asynchronous callback
- We could take the example of setTimeout method as it executes asynchronously
console.log("Javascript is awesome");
setTimeout(() => {
console.log("This codeblock runs after 2 seconds");
}, 2000);
console.log("Scribbler is awesome");
// Output
Javascript is awesome
Scribbler is awesome
This codeblock runs after 2 seconds
Callback Hell (Pyramid of Doom)
function saveOrder(orderId, userMail, callback) {
const order = {
orderId,
userMail
}
scrib.show(order)
callback(userMail); // Execute the callback function
}
function sendDetailsToSeller(orderId, userMail, callback) {
const details = {
orderId,
userMail
}
scrib.show(details)
callback(userMail);
}
function sendOrderEmail(userMail) {
scrib.show(userMail, "Order confirmed")
}
saveOrder("145908275","user@gmail.com", () => sendDetailsToSeller("145908275","user@gmail.com",sendOrderEmail));
// If you see we have to pass down the callbacks at multiple level in order to perform chaining operations.
- When callbacks nest too deeply, they become difficult to read and maintain.
🔴 Problem: Difficult to read, maintain, and debug.
✅ Solution: Promises or Async/Await.
Promises - our saviour from callback hell
- A Promise in JavaScript represents the eventual success or failure of an asynchronous operation. It provides a cleaner way to handle async tasks compared to traditional callbacks.
- It takes a function with two parameters:
- resolve → Call this when the async task is successful.
- reject → Call this when the async task fails.
- Promise States: A promise can be in one of three states:
- Pending → Initial state, neither fulfilled nor rejected.
- Fulfilled → The operation was successful (resolve() was called).
- Rejected → The operation failed (reject() was called).
Sample codes
Basic example
const basicPromise = new Promise((resolve, reject) => {
setTimeout(() => {
let success = true; // Simulating success or failure
if (success) {
resolve("Task completed successfully! ✅");
} else {
reject("Task failed ❌");
}
}, 2000);
});
basicPromise
.then((result) => {
scrib.show(result); // Output: Task completed successfully! ✅
})
.catch((error) => {
scrib.show(error); // Output: Task failed ❌ (if failed)
})
.finally(() => {
scrib.show("Promise execution completed.");
});
Data fetching with fetch method
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log("Fetch Error:", error));
Chaining promises methods
// Chaining promises method
new Promise((resolve) => {
setTimeout(() => resolve(10), 1000);
})
.then((num) => {
scrib.show(num); // 10
return num * 2;
})
.then((num) => {
scrib.show(num); // 20
return num * 3;
})
.then((num) => {
scrib.show(num); // 60
});
Promise methods
-
Promise.all
- Waits for all promises to resolve. If any promise rejects, the entire result is rejected. -
Promise.race
- Returns the first settled (fulfilled/rejected) promise. -
Promise.allSettled
- Waits for all promises to settle (resolve or reject) and returns their statuses. -
Promise.any
- Returns the first fulfilled promise, ignoring rejections.
const promise1 = new Promise((resolve) => {
setTimeout(() => resolve(Math.floor(3.14), 1000));
})
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve(Math.ceil(3.14), 1000));
})
const promise3 = new Promise((resolve) => {
setTimeout(() => resolve(Math.pow(3.14, 10), 1000));
})
// Promise.all
const promiseAll = Promise.all([promise1,promise2,promise3])
promiseAll.then(scrib.show())
// Promise.race
const promiseRace = Promise.race([promise1,promise2,promise3])
promiseRace.then(scrib.show())
// Promise.allSettled
const promiseAllSettled = Promise.allSettled([promise1,promise2,promise3])
promiseAllSettled.then(scrib.show())
// Promise.any
const promiseAny = Promise.any([promise1,promise2,promise3])
promiseAny.then(scrib.show())
- For even better async handling, async/await can be used, which simplifies working with promises.
Async/Await
-
async/await
is a modern JavaScript feature that simplifies working with asynchronous code. It allows you to write asynchronous code in a synchronous-like manner, making it easier to read, understand, and debug. - Why Use async/await?
- Before async/await, JavaScript developers handled asynchronous code using:
- Callbacks (led to callback hell)
- Promises (better, but still required .then() chaining)
- How
async/await
works - Declaring a function as async makes it return a promise automatically even if it is returning a simple value.
Sample code
Solving callback hell issue
// Async await example for callback hell issue
async function saveOrder(orderId, userMail, callback) {
const order = {
orderId,
userMail
}
scrib.show(order)
return order
}
async function sendDetailsToSeller(orderId, userMail, callback) {
const details = {
orderId,
userMail
}
scrib.show(details)
return details
}
async function sendOrderEmail(userMail) {
scrib.show(userMail, "Order confirmed")
return "Email sent"
}
async function processOrder(orderId, userMail) {
await saveOrder(orderId, userMail);
await sendDetailsToSeller(orderId, userMail);
await sendOrderEmail(userMail);
}
processOrder("145908275","user@gmail.com");
// Much readable and easy to manage
Data fetching
// Fetching data using async/await
async function fetchData() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); // ✅ Await fetch
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json(); // ✅ Await response.json()
return data;
}
fetchData()
.then(data => scrib.show("Fetched Data:", data))
.catch(error => scrib.show("Error:", error));
Combining loops with async/await for readable streams
// Combining async/await with loops
async function fetchTodos() {
let urls = [
"https://jsonplaceholder.typicode.com/todos/1",
"https://jsonplaceholder.typicode.com/todos/2",
"https://jsonplaceholder.typicode.com/todos/3"
];
for (let url of urls) {
let response = await fetch(url);
let data = await response.json();
scrib.show(data);
}
}
fetchTodos();
Checkout this embed to run the code example mentioned above
That's it for this post, Let me know if i could do any improvements in this article. Also, do check Scribbler.live website.
You can contact me on -
Instagram - https://www.instagram.com/supremacism__shubh/
LinkedIn - https://www.linkedin.com/in/shubham-tiwari-b7544b193/
Email - shubhmtiwri00@gmail.com
You can help me with some donation at the link below Thank you👇👇
https://www.buymeacoffee.com/waaduheck
Also check these posts as well

Button Component with CVA and Tailwind
Shubham Tiwari ・ Feb 12 '24

Top comments (2)
This makes their understanding very smooth for mr thanks for that , please make one on closures
Nice article and very good examples.. makes the concept easy to understand