Handling asynchronous operations is part of everyday JavaScript development. Whether fetching API data, reading from a database, or processing background tasks, async code is everywhere.
In JavaScript, two popular ways to manage this are Promises and Async/Await. While their syntax may differ, they’re deeply connected; in fact, async/await is just a cleaner way to work with promises.
Understanding Promises
A Promise represents the eventual result of an asynchronous operation. It has three states:
Pending - the operation is ongoing.
Fulfilled - the operation completed successfully.
Rejected - something went wrong.
Example: Basic Promise with Console Flow
console.log('Script Start');
function fetchData() {
return new Promise((resolve, reject) => {
console.log('Inside Promise - Starting async task...');
setTimeout(() => {
console.log('Async task complete - Resolving promise...');
resolve('Fetched Data');
}, 2000);
});
}
fetchData()
.then((data) => {
console.log('Promise Resolved with:', data);
})
.catch((error) => {
console.error('Promise Rejected with:', error);
});
console.log('Script End');
Output:
Script Start
Inside Promise - Starting async task…
Script End
Async task complete - Resolving promise…
Promise Resolved with: Fetched Data
Explanation:
The script runs top to bottom. The setTimeout is async, so "Script End" appears before "Promise Resolved..."
Understanding Async/Await
Async/Await simplifies working with Promises by using async functions and the await keyword to pause execution until the Promise is resolved.
Example: Async/Await Version with Clear Logs
console.log('Script Start');
function fetchData() {
return new Promise((resolve, reject) => {
console.log('Inside Promise - Starting async task...');
setTimeout(() => {
console.log('Async task complete - Resolving promise...');
resolve('Fetched Data');
}, 2000);
});
}
async function handleFetch() {
try {
console.log('Before await fetchData()...');
const data = await fetchData();
console.log('After await - Data received:', data);
} catch (error) {
console.error('Error caught:', error);
}
}
handleFetch();
console.log('Script End');
Output:
Script Start
Inside Promise - Starting async task…
Before await fetchData()...
Script End
Async task complete - Resolving promise…
After await - Data received: Fetched Data
Explanation:
The await keyword pauses only inside the async function. Outside logs continue immediately, proving that JavaScript remains non-blocking.