Open In App

Callbacks vs Promises vs Async/Await

Last Updated : 23 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Callbacks, Promises, and Async/Await are three different approaches in JavaScript for handling asynchronous operations. Let’s briefly discuss each.

Callback

Callbacks are functions passed as arguments to other functions, and they are executed after the completion of a specific task. Callbacks have been a traditional way of handling asynchronous operations in JavaScript.

Note: Callbacks can lead to “callback hell” or “pyramid of doom” when dealing with multiple nested asynchronous operations, making the code harder to read and maintain.

Example: fetchUserDataWithCallback simulates fetching user data from an API and then invokes a callback (processUserData) to process the data.

Javascript




// Callback function to process user data
function processUserData(data, callback) {
    console.log("Processing user data:", data);
    callback();
}
 
// Function to fetch user data with a callback
function fetchUserDataWithCallback(callback) {
    // Simulating an API request
    const userData = { id: 1, name: "John Doe" };
    callback(userData);
}
 
// Using the callback
fetchUserDataWithCallback((data) => {
    processUserData(data, () => {
        console.log("User data processed successfully.");
    });
});


Output

Processing user data: { id: 1, name: 'John Doe' }
User data processed successfully.

Promises

Promises were introduced to address the callback hell issue and provide a more structured way of handling asynchronous code. A Promise is an object representing the eventual completion or failure of an asynchronous operation.

Promises provide a more structured way to handle asynchronous code and simplify error handling. They can be chained using .then() and .catch().

Example: Here, fetchUserDataWithPromise returns a Promise, simulating the asynchronous nature of an API request. The .then() method handles the resolved value, and the .catch() method handles errors.

Javascript




// Function to fetch user data with a Promise
function fetchUserDataWithPromise() {
    // Simulating an API request
    const userData = { id: 1, name: "John Doe" };
 
    return new Promise((resolve, reject) => {
        if (userData) {
            resolve(userData);
        } else {
            reject("Error fetching user data.");
        }
    });
}
 
// Using the Promise
fetchUserDataWithPromise()
    .then((data) => {
        console.log("Processing user data:", data);
        console.log("User data processed successfully.");
    })
    .catch((error) => {
        console.error("Error:", error);
    });


Output

Processing user data: { id: 1, name: 'John Doe' }
User data processed successfully.

Async/Await

Async/Await is a syntactic sugar built on top of Promises. It allows writing asynchronous code that looks and behaves more like synchronous code, making it easier to read and understand.

Async/Await simplifies asynchronous code by allowing the use of the await keyword to pause the execution until the Promise is resolved. It’s particularly useful when dealing with multiple asynchronous operations.

Example: Here, fetchUserDataWithAsyncAwait returns a Promise, and processUserDataWithAsyncAwait is an asynchronous function that uses the await keyword to handle the resolved value.

Javascript




// Function to fetch user data with Async/Await
async function fetchUserDataWithAsyncAwait() {
    // Simulating an API request
    const userData = { id: 1, name: "John Doe" };
 
    return new Promise((resolve) => {
        resolve(userData);
    });
}
 
// Function to process user data using Async/Await
async function processUserDataWithAsyncAwait() {
    try {
        const data = await fetchUserDataWithAsyncAwait();
        console.log("Processing user data:", data);
        console.log("User data processed successfully.");
    } catch (error) {
        console.error("Error:", error);
    }
}
 
// Using Async/Await
processUserDataWithAsyncAwait();


Output

Processing user data: { id: 1, name: 'John Doe' }
User data processed successfully.

Differences between Callbacks, Promises, and Async/Await:

Parameter

Callbacks

Promises

Async/Await

Main focus

Manage asynchronous

Deliver a more robust explanation for managing asynchronous operations

Make asynchronous code appears synchronous improve code quality

Complexity

Less readable because of nesting or callback hell

More readable as compare to Callbacks

Highly readable with clean code.

Syntax

Function-based structure

Introduced the Promise object and methods like .then() and .catch()

Async and Await used

Use case

Suitable for simple cases

Perfect for complex asynchronous operations, managing multiple asynchronous and handle API calls

Use to maintain code in large applications improves the code quality.

Performance

Normally good in performance

Just overhead due to the promise creation

slight overhead as Comparable to promises

Debugging complexity

difficult to debug

Easier to debugging

Streamlines debugging by letting step through debugging similar to synchronous

Browser and Environment

JavaScript environments

Modern web browsers and Node.js

Modern web browsers and Node.js

Way of Error Handling

error handling separately

error handling with .catch() method

error handling using try and catch blocks

Similarity between Callbacks, Promises, and Async/Await:

  • Callbacks, Promises, and Async/Await they all are used to handle asynchronous operations in JavaScript. All these three are designed to handle the results of asynchronous operations. i.e. similarities in asynchronous operations and handling of asynchronous results.
  • They all handle errors in their own way, Callbacks use the error first convention, Promises uses the .catch() method, and Async/Await uses try and catch block.
  • Callbacks, Promises, and Async/Await they all operate on the JavaScript event loop. i.e. similarity in event loop utilization.
  • They all Callbacks, Promises, and Async/Await they all enable the execution of non-blocking code. This means JavaScript engines can execute other tasks/operations while waiting for an asynchronous operation to complete, they are similar in nature to Non-blocking code execution.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads