Async / Await
- This lesson explains how async/await improves asynchronous code readability.
Introduction to Async / Await
In modern JavaScript applications, many operations take time, such as:
Fetching data from a server
Reading files
Waiting for user actions
Calling APIs
Performing background tasks
Handling these operations without freezing the UI is possible using asynchronous JavaScript.
Earlier, JavaScript handled async operations using:
Callbacks
Promises
While Promises improved code readability, they still caused complex chaining.
To solve this problem, JavaScript introduced async / await.
What is Async / Await ?
Async / Await is a modern JavaScript feature built on top of Promises, which allows us to write asynchronous code that looks simple and synchronous.
Simple Definition
async / await allows asynchronous code to be written in a synchronous-like style, making it easier to read, write, and debug.
Why Async / Await Was Introduced
Problems with callbacks and promises:
Nested callbacks (callback hell)
Long .then() chains
Hard to read and debug
Async / await solves these problems by:
Improving readability
Reducing complexity
Making error handling easier
Relationship Between Promise and Async / Await
async functions always return a Promise
await pauses execution until the Promise resolves
Async / await is just syntactic sugar over Promises
The async Keyword
What Does async Do ?
The async keyword is used to define an asynchronous function.
async function myFunction() {
return "Hello";
}
Even though it looks like a normal return, JavaScript automatically wraps it inside a Promise.
JavaScript Async Function with Promise
This code demonstrates how an async function automatically returns a Promise and its result is handled using .then().
async function greet() {
return "Welcome";
}
greet().then(result => {
console.log(result);
});
The await Keyword
What Does await Do ?
The await keyword is used inside an async function to pause execution until a Promise is resolved.
let result = await somePromise;
Important points:
await can only be used inside async functions
It waits for Promise resolution
It does not block the main thread
JavaScript Async/Await with Promise Example
This code demonstrates how async/await is used to handle Promises in a more readable way by waiting for asynchronous data before continuing execution.
function fetchData() {
return new Promise(resolve => {
setTimeout(() => {
resolve("Data received");
}, 2000);
});
}
async function showData() {
let data = await fetchData();
console.log(data);
}
showData();
Execution Flow Explanation
showData() is called
fetchData() returns a Promise
await pauses execution inside showData()
After 2 seconds, Promise resolves
Execution resumes and logs data
Async / Await vs Promises
Using Promises
JavaScript Promises vs Async/Await (Promise Handling)
This code demonstrates handling asynchronous operations using Promises with .then() and .catch() for success and error handling.
fetchData()
.then(data => {
console.log(data);
})
.catch(error => {
console.log(error);
});
JavaScript Async/Await Error Handling Example
This code demonstrates how async/await with try...catch is used to handle asynchronous operations and errors in a cleaner way than Promises.
async function getData() {
try {
let data = await fetchData();
console.log(data);
} catch (error) {
console.log(error);
}
}
Async / await is cleaner and easier to understand.
Error Handling with Async / Await
Using try...catch
JavaScript Fetch API with Async/Await
This code demonstrates how to fetch data from an API using async/await and handle the response and errors using try...catch.
async function fetchUser() {
try {
let response = await fetch("https://api.example.com/user");
let data = await response.json();
console.log(data);
} catch (error) {
console.log("Error occurred:", error);
}
}
Errors are handled just like synchronous code.
JavaScript Async/Await Without Error Handling
This code demonstrates an async function where a rejected Promise is awaited without try...catch, which can cause an unhandled error.
Without try...catch
async function test() {
let result = await Promise.reject("Failed");
}
This causes an unhandled promise rejection.
Multiple await Statements
Async functions can contain multiple await calls.
JavaScript Sequential Async/Await Execution
This code demonstrates how multiple asynchronous tasks are executed one after another using async/await in a sequential flow.
async function processData() {
let a = await firstTask();
let b = await secondTask();
let c = await thirdTask();
console.log(a, b, c);
}
Each await waits for the previous one to finish.
Parallel Execution Using Promise.all()
Awaiting tasks one by one can be slow.
JavaScript Parallel Execution with Promise.all
This code demonstrates how multiple asynchronous tasks run in parallel using Promise.all and return all results together.
async function loadAll() {
let results = await Promise.all([
taskOne(),
taskTwo(),
taskThree()
]);
console.log(results);
}
This runs tasks in parallel.
Async / Await with Fetch API
JavaScript Fetch API Example with Async/Await
This code demonstrates how to fetch data from an API using async/await and convert the response into JSON format.
async function getPosts() {
let response = await fetch("https://jsonplaceholder.typicode.com/posts");
let posts = await response.json();
console.log(posts);
}
getPosts();
This is a very common real-world use case.
Common Mistakes
Using await outside an async function
Forgetting error handling
Expecting await to block the entire program
Writing sequential awaits unnecessarily
Not understanding that async returns a Promise
Best Practices for Async / Await
Always use try...catch
Use Promise.all() for independent tasks
Keep async functions small
Avoid mixing .then() with await
Handle network and runtime errors properly
Real-World Use Cases
API calls
Authentication systems
Data loading
File handling
Timers and delays
Backend communication