JavaScript Async/Await
Write asynchronous code that looks synchronous
β‘ What is Async/Await?
Async/Await is a syntax that makes it easier to work with Promises. It allows you to write asynchronous code that looks and behaves like synchronous code.
// Without async/await (using promises)
function fetchData() {
return fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data));
}
// With async/await (cleaner!)
async function fetchData() {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
}
Key Concepts
async
Makes a function return a Promise
async function myFunction() {
return 'Hello';
}
await
Pauses function until Promise resolves
const result = await promise;
Error Handling
Use try/catch for errors
try {
await promise;
} catch (error) {
console.log(error);
}
Clean Code
No more callback hell
// Readable and clean
const data = await getData();
πΉ Basic Async/Await
Here's how to use async/await:
// Creating an async function
async function greetUser() {
return 'Hello, User!';
}
// Calling async function
greetUser().then(message => console.log(message));
// Or using await (inside another async function)
async function main() {
const greeting = await greetUser();
console.log(greeting);
}
main();
// Async function with delay
async function delayedMessage() {
// Create a promise that resolves after 2 seconds
const delay = new Promise(resolve => {
setTimeout(() => resolve('Message after delay!'), 2000);
});
console.log('Waiting...');
const message = await delay;
console.log(message);
}
delayedMessage();
Output:
Hello, User!
Hello, User!
Waiting...
(After 2 seconds...) Message after delay!
πΉ Error Handling
Use try/catch blocks to handle errors in async functions:
// Function that might fail
async function riskyOperation() {
const random = Math.random();
if (random > 0.5) {
return 'Success!';
} else {
throw new Error('Operation failed!');
}
}
// Handling errors with try/catch
async function handleRiskyOperation() {
try {
const result = await riskyOperation();
console.log('Result:', result);
} catch (error) {
console.log('Error caught:', error.message);
} finally {
console.log('Operation completed');
}
}
handleRiskyOperation();
// Multiple operations with error handling
async function multipleOperations() {
try {
const result1 = await riskyOperation();
console.log('First operation:', result1);
const result2 = await riskyOperation();
console.log('Second operation:', result2);
} catch (error) {
console.log('One of the operations failed:', error.message);
}
}
multipleOperations();
Output (example):
Result: Success!
Operation completed
First operation: Success!
One of the operations failed: Operation failed!
πΉ Real-World Example
Here's a practical example of fetching user data:
// Simulating API calls
function fetchUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) {
resolve({ id: id, name: 'John Doe', email: '[email protected]' });
} else {
reject(new Error('Invalid user ID'));
}
}, 1000);
});
}
function fetchUserPosts(userId) {
return new Promise(resolve => {
setTimeout(() => {
resolve([
{ id: 1, title: 'First Post', content: 'Hello World!' },
{ id: 2, title: 'Second Post', content: 'Learning JavaScript!' }
]);
}, 1500);
});
}
// Using async/await to fetch user and their posts
async function getUserData(userId) {
try {
console.log('Fetching user data...');
const user = await fetchUser(userId);
console.log('User found:', user.name);
console.log('Fetching user posts...');
const posts = await fetchUserPosts(user.id);
console.log('Posts found:', posts.length);
return {
user: user,
posts: posts
};
} catch (error) {
console.log('Error:', error.message);
return null;
}
}
// Using the function
async function displayUserProfile() {
const userData = await getUserData(123);
if (userData) {
console.log('Profile loaded successfully!');
console.log('User:', userData.user.name);
console.log('Posts:', userData.posts.map(p => p.title));
}
}
displayUserProfile();
Output:
Fetching user data...
(After 1 second...) User found: John Doe
Fetching user posts...
(After 2.5 seconds...) Posts found: 2
Profile loaded successfully!
User: John Doe
Posts: ["First Post", "Second Post"]
πΉ Parallel vs Sequential
Control how async operations run:
// Sequential (one after another)
async function sequential() {
console.log('Sequential start');
const start = Date.now();
const result1 = await delay(1000, 'First');
const result2 = await delay(1000, 'Second');
const result3 = await delay(1000, 'Third');
const end = Date.now();
console.log('Sequential results:', [result1, result2, result3]);
console.log('Sequential time:', end - start, 'ms');
}
// Parallel (all at once)
async function parallel() {
console.log('Parallel start');
const start = Date.now();
const [result1, result2, result3] = await Promise.all([
delay(1000, 'First'),
delay(1000, 'Second'),
delay(1000, 'Third')
]);
const end = Date.now();
console.log('Parallel results:', [result1, result2, result3]);
console.log('Parallel time:', end - start, 'ms');
}
// Helper function
function delay(ms, value) {
return new Promise(resolve => {
setTimeout(() => resolve(value), ms);
});
}
// Run both examples
async function compare() {
await sequential(); // Takes ~3 seconds
await parallel(); // Takes ~1 second
}
compare();
Output:
Sequential start
(After 3 seconds...) Sequential results: ["First", "Second", "Third"]
Sequential time: 3003 ms
Parallel start
(After 1 second...) Parallel results: ["First", "Second", "Third"]
Parallel time: 1002 ms