Skip to main content

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.

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.
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!