Mastering Asynchronous JavaScript: Callbacks, Promises, and Async/Await

In this post, we will see about Mastering Asynchronous JavaScript: Callbacks, Promises, and Async/Await.

1. Callbacks

A callback is a function that is passed as an argument to another function, which is immediately executed when the first function has fully accomplished its task. Callbacks used to be the former method of dealing with asynchronous operations the time before promises orwe async/await came into being.

function fetchData(callback) {
    setTimeout(() => {
        callback("Data fetched");
    }, 1000);
}

fetchData((data) => {
    console.log(data); // Output after 1 second: "Data fetched"
});

Challenges with Callbacks:

Squeezing of a lot of callbacks within any level of the source code, which is more often than not, a clear sign of the dangerous and unresolved situation, know as callback hell

Example code:

function fetchData(callback) {
    setTimeout(() => {
        console.log("Fetching data...");
        callback();
    }, 1000);
}

function processData(callback) {
    setTimeout(() => {
        console.log("Processing data...");
        callback();
    }, 1000);
}

fetchData(() => {
    processData(() => {
        console.log("Data ready");
    });
});

2. Promises

A promise represents a value that will be available now, in the future, or never (in case of errors). It’s an object that can be in one of these states:

Pending: Initial state, not yet resolved or rejected.

Fulfilled: Operation completed successfully.

Rejected: Operation failed

3. Async/Await
Async and await gives a much cleaner and cohesive look to the standard, but technically asynchronous code can be handled or made to run synchronously. async functions will always return a promise, and await, in turn, allows the function to stop the execution unless the promise’s resolution event takes place.

Benefits of Async/Await:

  • Step by step, the code becomes synchronous because a promise waits for the previous one to finish.
  • Based on the asynchronous nature of JavaScript, the code can be written making it closely resemble synchronous semantics.
  • By passing (spreading) the “tasks” prop

Error Handling in Async/Await:

const fetchData = async () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => reject("Error fetching data"), 1000);
    });
};

const execute = async () => {
    try {
        const data = await fetchData();
        console.log(data);
    } catch (error) {
        console.error(error); // Output: "Error fetching data"
    }
};

execute();

Conclusion

  • Callbacks may be a simple way to write bad codes with numerous and hard-to-read nestings.
  • The adoption of Promises as an alternative way handles asynchronous operations has to be coupled with chaining and much better error handling.
  • Await has simplified the asynchronous code writing system more than ever before. It is almost the same with synchronous programming language and has become the most commonly used modern approach as well.

 

 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top