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.