Async & Await Syntax
While Promises solve Callback Hell, chaining multiple .then() and .catch() blocks can still become difficult to read.
Introduced in ES8 (ES2017), async and await provide a cleaner, syntactical wrapper around Promises. They let you write asynchronous code that reads like synchronous code.
1. The async Keyword
By prefixing a function with the async keyword, you guarantee that it always returns a Promise. If the function returns a non-promise value, JS automatically wraps it in a resolved Promise.
async function greet() {
return "Hello!"; // Wrapped in a resolved Promise
}
greet().then(val => console.log(val)); // "Hello!"2. The await Keyword
The await keyword can only be used inside an async function.
It tells the JavaScript engine to pause execution of the function until the Promise resolves or rejects, then returns the resolved value. This pauses execution without blocking the browser's main thread.
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function runSequence() {
console.log("Start");
await delay(1000); // Pauses code here for 1 second
console.log("End");
}
runSequence();3. Error Handling: try...catch
With async/await, you don't use .catch(). Instead, you handle errors using standard synchronous try...catch blocks:
function fetchProfile() {
return new Promise((resolve, reject) => {
setTimeout(() => reject("Network Timeout"), 1000);
});
}
async function displayUserProfile() {
try {
const profile = await fetchProfile();
console.log(profile);
} catch (error) {
// Captures the rejected value of the awaited promise
console.error("Failed to load profile:", error);
} finally {
console.log("Finished rendering UI");
}
}
displayUserProfile();4. Concurrent execution with await
A common mistake with async/await is invoking independent operations sequentially, creating a performance bottleneck:
// AVOID (Slow: takes 3 seconds total):
async function loadData() {
const users = await fetchUsers(); // Takes 1.5s
const posts = await fetchPosts(); // Takes 1.5s
}Instead, start the operations first, then await their aggregated results using Promise.all:
// BETTER (Fast: takes 1.5 seconds total):
async function loadDataCorrectly() {
const usersPromise = fetchUsers();
const postsPromise = fetchPosts();
// Await parallel execution:
const [users, posts] = await Promise.all([usersPromise, postsPromise]);
}In the next guide, we will learn how to make actual network HTTP requests using the browser's fetch() API.