Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
JavaScript is a language that heavily relies on asynchronous programming. When dealing with tasks that take time to complete (such as fetching data, file operations, or timers), JavaScript uses callbacks, callback hell, and promises to manage execution flow effectively.
A callback is a function passed as an argument to another function, which gets executed later when required. Callbacks allow us to handle asynchronous operations effectively.
setTimeout(()=>{
console.log('Printing after 5 seconds');
}, 5000);
Here’s a more explicit example of a function accepting a callback:
function hiFunc(param1, func1) {
console.log('Value of param Passed is ' + param1);
func1();
}
hiFunc(10, function () {
console.log('This gets executed afterwards');
});
In this example, func1
is executed after the hiFunc
function logs the value of param1
.
Consider an example where we need to create an order, proceed to payment, and then display a confirmation:
function createOrder(product, callback) {
console.log('Creating an order with', product);
let createdOrderNumber = Math.floor((Math.random() * 1000) + 1);
callback(createdOrderNumber);
}
function proceedToPayment(orderNumber, callback) {
console.log('Moving to Payment Gateway for Order#', orderNumber);
let createdPaymentNumber = Math.floor((Math.random() * 1000) + 1);
callback(createdPaymentNumber);
}
function displayConfirmation(paymentNumber, callback) {
console.log('Payment Successful!! Payment Id #', paymentNumber);
callback();
}
// Execution
createOrder('Jacket', (param1) => {
proceedToPayment(param1, (param2) => {
displayConfirmation(param2, () => {
console.log('Finally Over');
});
});
});
This method ensures sequential execution, but as the number of nested callbacks increases, it leads to callback hell.
Callback hell refers to deeply nested and hard-to-read callback structures, which make the code difficult to manage and debug.
let value = 1;
setTimeout(function () {
console.log(value++);
setTimeout(function () {
console.log(value++);
setTimeout(function () {
console.log(value++);
}, 1000);
setTimeout(function () {
console.log(value++);
}, 1000);
}, 1000);
}, 1000);
This deeply nested structure makes it hard to maintain and scale. To solve this, we use Promises.
A Promise is an object representing a future value. It can be in one of three states:
Promises help in writing cleaner, more manageable asynchronous code.
function createOrder(product) {
return new Promise(function(resolve, reject) {
console.log('Creating an order with', product);
let createdOrderNumber = Math.floor((Math.random() * 1000) + 1);
setTimeout(function () {
resolve(createdOrderNumber);
}, 3000);
});
}
function proceedToPayment(orderNumber) {
return new Promise(function(resolve, reject) {
let createdPaymentNumber = Math.floor((Math.random() * 1000) + 1);
console.log('Moving to Payment Gateway for Order#', orderNumber, 'with payment number', createdPaymentNumber);
setTimeout(function () {
resolve(createdPaymentNumber);
}, 2000);
});
}
function displayConfirmation(paymentNumber) {
return new Promise(function(resolve, reject) {
console.log('Payment Successful!! Payment Id #', paymentNumber);
setTimeout(function () {
resolve();
}, 1000);
});
}
// Using Promises for Better Readability
const product = 'Shoes';
createOrder(product)
.then((orderNumber) => {
console.log(orderNumber);
return proceedToPayment(orderNumber);
})
.then((paymentNumber) => {
console.log(paymentNumber);
return displayConfirmation(paymentNumber);
})
.catch((err) => {
console.log('Error:', err);
})
.finally(() => {
console.log('This is the end statement');
});
Async/Await makes asynchronous code look more like synchronous code, improving readability.
async function processOrder(product) {
try {
let orderNumber = await createOrder(product);
console.log(orderNumber);
let paymentNumber = await proceedToPayment(orderNumber);
console.log(paymentNumber);
await displayConfirmation(paymentNumber);
console.log('Process Completed Successfully');
} catch (err) {
console.log('Error:', err);
} finally {
console.log('This is the end statement');
}
}
processOrder('Shoes');
Feature | Promises | Async/Await |
---|---|---|
Readability | Moderate | High |
Error Handling | catch() blocks | try/catch blocks |
Code Structure | Chained .then() | Linear, sequential style |
Debugging | More complex | Easier to debug |
Understanding and using these concepts effectively will help in writing clean and efficient JavaScript code!