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