Callbacks vs Promises vs Async/Await
Last Updated :
23 Jan, 2024
Callbacks, Promises, and Async/Await are three different approaches in JavaScript for handling asynchronous operations. Let’s briefly discuss each.
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
function processUserData(data, callback) {
console.log( "Processing user data:" , data);
callback();
}
function fetchUserDataWithCallback(callback) {
const userData = { id: 1, name: "John Doe" };
callback(userData);
}
fetchUserDataWithCallback((data) => {
processUserData(data, () => {
console.log( "User data processed successfully." );
});
});
|
Output
Processing user data: { id: 1, name: 'John Doe' }
User data processed successfully.
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 fetchUserDataWithPromise() {
const userData = { id: 1, name: "John Doe" };
return new Promise((resolve, reject) => {
if (userData) {
resolve(userData);
} else {
reject( "Error fetching user data." );
}
});
}
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 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
async function fetchUserDataWithAsyncAwait() {
const userData = { id: 1, name: "John Doe" };
return new Promise((resolve) => {
resolve(userData);
});
}
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);
}
}
processUserDataWithAsyncAwait();
|
Output
Processing user data: { id: 1, name: 'John Doe' }
User data processed successfully.
Differences between Callbacks, Promises, and Async/Await:
Manage asynchronous
|
Deliver a more robust explanation for managing asynchronous operations
|
Make asynchronous code appears synchronous improve code quality
|
Less readable because of nesting or callback hell
|
More readable as compare to Callbacks
|
Highly readable with clean code.
|
Function-based structure
|
Introduced the Promise object and methods like .then() and .catch()
|
Async and Await used
|
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.
|
Normally good in performance
|
Just overhead due to the promise creation
|
slight overhead as Comparable to promises
|
difficult to debug
|
Easier to debugging
|
Streamlines debugging by letting step through debugging similar to synchronous
|
JavaScript environments
|
Modern web browsers and Node.js
|
Modern web browsers and Node.js
|
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.
Share your thoughts in the comments
Please Login to comment...