Promise
Callback Review
- Callbacks are a traditional way to manage asynchronous code but can lead to callback hell with nested functions.
function fetchData(callback) {
setTimeout(() => {
callback("Data received");
}, 1000);
}
fetchData((data) => {
console.log(data);
});The
fetchDatafunction simulates fetching data with a delay and then calls the provided callback function with the data. As more asynchronous operations are nested, this can lead to "callback hell."
Introducing Promises
- Promises provide a cleaner and more structured way to handle asynchronous operations by chaining then and catch methods.
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
fetchData.then((data) => {
console.log(data);
}).catch((error) => {
console.error(error);
});The example shows a
Promisethat resolves after a delay. The.thenmethod handles the resolved value, and.catchhandles any errors. This approach avoids deeply nested callbacks and makes the code more readable.
Chaining Promises
- Chaining promises ensures that asynchronous tasks are executed in the correct order and errors are handled gracefully.
const fetchData = () => new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
fetchData()
.then((data) => {
console.log(data);
return "Next task";
})
.then((nextTask) => {
console.log(nextTask);
})
.catch((error) => {
console.error(error);
});This example shows how promises can be chained to execute tasks sequentially. The first
.thenhandles the initial promise, and the second.thenhandles the subsequent task. Errors in any part of the chain are caught by.catch.
Error Handling
- Error handling is essential in asynchronous code to prevent unexpected behavior and ensure proper flow of execution.
- Promises allow for centralized error handling using the
.catchmethod at the end of the chain.
const fetchData = () => new Promise((resolve, reject) => {
setTimeout(() => {
reject("Error occurred");
}, 1000);
});
fetchData()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});The
.catchmethod ensures that any errors are handled properly, preventing the application from crashing unexpectedly.
Async/Await
- Async/await simplifies asynchronous programming by allowing developers to write asynchronous code in a synchronous style, making it easier to read and maintain.
const fetchData = () => new Promise((resolve) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
async function getData() {
const data = await fetchData();
console.log(data);
}
getData();The
asyncfunctiongetDatausesawaitto pause execution untilfetchDataresolves. This approach makes asynchronous code look and behave more like synchronous code, enhancing readability and maintainability.
Context of Promises with Async/Await
- Understanding how to use async/await within the context of promises is crucial for effective asynchronous programming in JavaScript.
const fetchData = (isError) => new Promise((resolve, reject) => {
setTimeout(() => {
if (isError) {
reject("Error occurred");
} else {
resolve("Data received");
}
}, 1000);
});
async function getData() {
try {
const data = await fetchData(false);
console.log(data);
} catch (error) {
console.error(error);
}
}
getData();This example shows how
async/awaitis used in conjunction with promises. Thetry...catchblock handles any errors that occur during the asynchronous operation, demonstrating effective error handling within anasyncfunction.