Node.js7 min read
Async/Await: Clean Async Code
Master async/await for writing synchronous-looking asynchronous code. The modern way to handle async operations.
Sarah Chen
December 19, 2025
0.0k0
Async/Await: Clean Async Code
Async/await makes Promises look like synchronous code. It's the modern standard.
Basic Syntax
// Regular Promise
fetchUser()
.then(user => console.log(user));
// Async/await
async function getUser() {
const user = await fetchUser();
console.log(user);
}
async Function
// Always returns a Promise
async function greet() {
return 'Hello';
}
greet().then(msg => console.log(msg)); // Hello
await Keyword
async function loadData() {
// Pauses here until Promise resolves
const data = await fetchData();
// Then continues
console.log(data);
return data;
}
Error Handling with try/catch
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error('User not found');
}
const user = await response.json();
return user;
} catch (error) {
console.error('Error:', error.message);
throw error; // Re-throw if needed
}
}
Sequential vs Parallel
// Sequential - slower
async function sequential() {
const user = await fetchUser(); // Wait 1s
const posts = await fetchPosts(); // Wait 1s
// Total: 2s
}
// Parallel - faster
async function parallel() {
const [user, posts] = await Promise.all([
fetchUser(), // Start immediately
fetchPosts() // Start immediately
]);
// Total: 1s (max of both)
}
Async in Loops
// Sequential (one at a time)
async function processSequential(ids) {
for (const id of ids) {
const data = await fetchData(id);
console.log(data);
}
}
// Parallel (all at once)
async function processParallel(ids) {
const promises = ids.map(id => fetchData(id));
const results = await Promise.all(promises);
return results;
}
Real-World Example
const fs = require('fs').promises;
async function processFile(inputPath, outputPath) {
try {
// Read file
const content = await fs.readFile(inputPath, 'utf8');
// Process
const processed = content.toUpperCase();
// Write result
await fs.writeFile(outputPath, processed);
console.log('Done!');
} catch (error) {
console.error('Failed:', error.message);
}
}
Top-Level Await (ES Modules)
// In .mjs files or "type": "module"
const config = await fs.readFile('config.json', 'utf8');
console.log(config);
Arrow Functions with Async
const fetchData = async () => {
const response = await fetch('/api/data');
return response.json();
};
// In array methods
const results = await Promise.all(
items.map(async (item) => {
return await processItem(item);
})
);
Common Patterns
// Retry logic
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === retries - 1) throw error;
await delay(1000); // Wait before retry
}
}
}
// Timeout
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(id);
return response;
} catch (error) {
clearTimeout(id);
throw error;
}
}
Key Takeaway
Async/await is syntactic sugar over Promises. Use async to mark functions, await to pause for Promises, try/catch for errors. For parallel operations, use Promise.all(). It's the cleanest way to write async Node.js code.
#Node.js#Async/Await#Promises#Beginner