Async/Await in JavaScript
Hello! In this guide, we’ll explore how the async
and await
keywords work in JavaScript. These features make it easier to work with Promises and asynchronous code. Let’s dive into the details!
1. What is async
/await
?
async
and await
are syntactic sugar built on top of Promises. They make asynchronous code look and behave like synchronous code, improving readability and maintainability.
1.1 async
Keyword
The async
keyword is used to define an asynchronous function. An async
function always returns a Promise.
Example:
async function fetchData() {
return "Data fetched!";
}
fetchData().then((result) => console.log(result)); // Data fetched!
1.2 await
Keyword
The await
keyword can only be used inside an async
function. It pauses the execution of the function until the Promise resolves.
Example:
async function fetchData() {
let result = await Promise.resolve("Data fetched!");
console.log(result); // Data fetched!
}
fetchData();
2. Error Handling with try
/catch
You can use try
/catch
blocks to handle errors in async
functions, making it easier to manage rejected Promises.
Example:
async function fetchData() {
try {
let result = await Promise.reject("Error occurred!");
} catch (error) {
console.log(error); // Error occurred!
}
}
fetchData();
3. Using await
with Multiple Promises
You can use await
to handle multiple Promises by awaiting each one sequentially, or you can use Promise.all()
to await all Promises in parallel.
3.1 Sequential Promise Handling
Example:
async function fetchSequential() {
let result1 = await Promise.resolve("First result");
let result2 = await Promise.resolve("Second result");
console.log(result1); // First result
console.log(result2); // Second result
}
fetchSequential();
3.2 Parallel Promise Handling with Promise.all()
Example:
async function fetchParallel() {
let [result1, result2] = await Promise.all([
Promise.resolve("First result"),
Promise.resolve("Second result"),
]);
console.log(result1); // First result
console.log(result2); // Second result
}
fetchParallel();
4. Async Functions Return Promises
Even if an async
function doesn’t explicitly return a Promise, it will still return one implicitly.
Example:
async function fetchData() {
return "Data fetched!";
}
console.log(fetchData()); // Promise {<resolved>: "Data fetched!"}
5. Handling Timeouts with await
You can simulate a delay or timeout using await
by combining it with setTimeout()
wrapped in a Promise.
Example:
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function fetchData() {
console.log("Fetching data...");
await delay(2000); // Wait for 2 seconds
console.log("Data fetched!");
}
fetchData();
Output:
Fetching data...
(Data is fetched after 2 seconds)
Data fetched!
6. Avoiding await
Pitfalls
Using await
inside loops can cause performance issues if not used carefully. To avoid delays, use Promise.all()
to run Promises in parallel when possible.
Example of Sequential Delay (Not Recommended):
async function fetchItemsSequential() {
const items = [1, 2, 3];
for (let item of items) {
await delay(1000);
console.log(`Fetched item ${item}`);
}
}
fetchItemsSequential();
// Takes 3 seconds total, 1 second for each item.
Example of Parallel Execution (Recommended):
async function fetchItemsParallel() {
const items = [1, 2, 3];
await Promise.all(
items.map(async (item) => {
await delay(1000);
console.log(`Fetched item ${item}`);
})
);
}
fetchItemsParallel();
// Takes 1 second total, runs all fetches in parallel.
async
and await
make it easier to write and manage asynchronous JavaScript code. They provide a clean, readable alternative to Promises while still maintaining the same functionality. Mastering these features will help you handle async tasks like API calls, timeouts, and more efficiently. Happy coding!