JavaScript Promises Tutorial - Section 4: Async/Await
Async/await is syntactic sugar over Promises that makes asynchronous code look and behave like synchronous code.
fetchUser(1)
.then(user => fetchPosts(user.id))
.then(posts => console.log(posts))
.catch(error => console.error(error));
async function getPosts() {
try {
const user = await fetchUser(1);
const posts = await fetchPosts(user.id);
console.log(posts);
} catch (error) {
console.error(error);
}
}
Benefits:
The async keyword makes a function return a Promise:
async function myFunction() {
return 'Hello';
}
// Equivalent to:
function myFunction() {
return Promise.resolve('Hello');
}
myFunction().then(value => console.log(value)); // 'Hello'
1. Always returns a Promise
async function getValue() {
return 42;
}
console.log(getValue()); // Promise { 42 }
2. Can use await inside
async function fetchData() {
const data = await fetch('/api/data');
return data;
}
3. Works with all function types
// Function declaration
async function func1() {}
// Function expression
const func2 = async function() {};
// Arrow function
const func3 = async () => {};
// Method
const obj = {
async method() {}
};
The await keyword pauses execution until a Promise settles:
async function example() {
console.log('Before await');
const result = await Promise.resolve('value');
console.log('After await');
console.log(result); // 'value'
}
1. Only works inside async functions
// ❌ Error: await outside async function
const result = await fetchData();
// ✅ Correct
async function getData() {
const result = await fetchData();
}
2. Pauses execution, but doesn't block
async function demo() {
console.log('1');
await delay(1000);
console.log('2'); // Runs after 1 second
}
demo();
console.log('3'); // Runs immediately
// Output: 1, 3, 2
Before:
function getUser() {
return fetchUser(1)
.then(user => {
console.log('User:', user);
return user;
});
}
After:
async function getUser() {
const user = await fetchUser(1);
console.log('User:', user);
return user;
}
Before:
function processOrder(orderId) {
return fetchOrder(orderId)
.then(order => validateOrder(order))
.then(validOrder => processPayment(validOrder))
.then(payment => sendConfirmation(payment));
}
After:
async function processOrder(orderId) {
const order = await fetchOrder(orderId);
const validOrder = await validateOrder(order);
const payment = await processPayment(validOrder);
const confirmation = await sendConfirmation(payment);
return confirmation;
}
Before:
function getData() {
return fetchData()
.then(data => processData(data))
.catch(error => {
console.error('Error:', error);
throw error;
});
}
After:
async function getData() {
try {
const data = await fetchData();
return await processData(data);
} catch (error) {
console.error('Error:', error);
throw error;
}
}
async function getUserProfile(userId) {
const user = await fetch(`/api/users/${userId}`).then(r => r.json());
const posts = await fetch(`/api/users/${userId}/posts`).then(r => r.json());
return {
user,
posts,
postCount: posts.length
};
}
getUserProfile(1)
.then(profile => console.log(profile))
.catch(error => console.error(error));
| Feature | Promises | Async/Await |
|---|---|---|
| Syntax | .then() chains |
await keyword |
| Readability | Can get nested | Linear, like sync code |
| Error Handling | .catch() |
try/catch |
| Debugging | Harder | Easier |
| Compatibility | ES6 (2015) | ES8 (2017) |
async function slowFunction() {
await delay(3000);
console.log('Done');
}
slowFunction(); // Doesn't block
console.log('This runs immediately');
Under the hood, async/await uses Promises:
async function example() {
return 'value';
}
// Same as:
function example() {
return Promise.resolve('value');
}
async makes a function return a Promiseawait pauses execution until Promise settlesawait inside async functionstry/catch for error handlingYou've completed the core lessons! Continue exploring advanced topics and real-world patterns in the remaining sections.