async and await are JavaScript keywords that provide a cleaner, more readable way to handle asynchronous operations without relying on complex Promise chains (.then() and .catch()). They make asynchronous code look and behave more like traditional synchronous code, which simplifies writing and maintaining your applications.
Async
async (Asynchronous): Placed before a function declaration to turn it into an asynchronous function. An async function always returns a Promise. If you return a normal value, JavaScript automatically wraps it inside a resolved Promise.
Await
await (Wait for resolution): Used inside an async function to pause code execution until a Promise resolves or rejects. It allows you to assign the resolved value of a Promise directly to a variable.
We use async/await to make asynchronous code look and behave more like normal synchronous code, making it easier to read and maintain.
- We use async/await to execute multiple dependent asynchronous operations in a simple top-to-bottom manner. It allows us to wait for the result of one Promise before using it in the next step, making the code easier to read and manage.
Without async/await (using Promise)
<script>
function getUserById(id){
console.log("Got User id: ",id);
return new Promise((resolve,rejcet)=>{
setTimeout(()=>{
resolve({id:id, name: 'vicky'});
},1000)
})
}
function getSubcriptions(id){
console.log("Got User Subscriptions for: ",id);
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve([
{id:1, title:'netfilx'},
{id:2, title:'hotstar'},
{id:3, title:'AmazonPrime'}
]);
},2000)
})
}
function calculateTotal(subcriptions){
console.log("Subscriptions: ",subcriptions);
return new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(subcriptions.length * 100);
},3000)
})
}
getUserById(1)
.then(getSubcriptions)
.then(calculateTotal)
.then(cost =>{
console.log("total Cost: ",cost);
})
</script>
Ouput
Got User id: 1
promise.html:22 Got User Subscriptions for: {id: 1, name: 'vicky'}
promise.html:36 Subscriptions: (3) [{…}, {…}, {…}]
promise.html:49 total Cost: 300
With async/await (using Promise)
<script>
function getUserById(id) {
console.log("Got User id: ", id);
return new Promise((resolve, rejcet) => {
setTimeout(() => {
resolve({ id: id, name: 'vicky' });
}, 1000)
})
}
function getSubcriptions(id) {
console.log("Got User Subscriptions for: ", id);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([
{ id: 1, title: 'netfilx' },
{ id: 2, title: 'hotstar' },
{ id: 3, title: 'AmazonPrime' }
]);
}, 2000)
})
}
function calculateTotal(subcriptions) {
console.log("Subscriptions: ", subcriptions);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(subcriptions.length * 100);
}, 3000)
})
}
async function displayTotalCost() {
try {
//call the promise one by one
const userInfo = await getUserById(1);
const subcriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subcriptions);
console.log("total Cost: ", total);
console.log("Everything is Fetched...");
} catch (error) {
console.error("Catch-block: ",error);
}
}
displayTotalCost();
</script>
Output
Got User id: 1
promise_With_Async.html:24 Got User Subscriptions for: {id: 1, name: 'vicky'}
promise_With_Async.html:38 Subscriptions: (3) [{…}, {…}, {…}]
promise_With_Async.html:54 total Cost: 300
promise_With_Async.html:55 Everything is Fetched...
In our example:
Get the user details.
Get that user's subscriptions.
Calculate the total cost using those subscriptions.
Display the result.
Each step depends on the previous step, so await is useful.
Why use async/await here?
1. Better Readability
Without async/await
getUserById(1)
.then(userInfo => {
return getSubcriptions(userInfo);
})
.then(subscriptions => {
return calculateTotal(subscriptions);
})
.then(total => {
console.log(total);
});
With async/await
const userInfo = await getUserById(1);
const subscriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subscriptions);
2. Handles Dependent Operations Easily
Your operations depend on each other:
User
↓
Subscriptions
↓
Total Cost
You cannot calculate the total before getting subscriptions.
await naturally enforces this order.
const userInfo = await getUserById(1);
const subscriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subscriptions);
3. Easier Error Handling
A single try...catch can handle errors from all three Promises.
try {
const userInfo = await getUserById(1);
const subscriptions = await getSubcriptions(userInfo);
const total = await calculateTotal(subscriptions);
} catch(error) {
console.log(error);
}
Without async/await, you'd usually handle errors with .catch().
4. Code Looks Synchronous
Although each function takes time:
getUserById -> 1 second
getSubcriptions -> 2 seconds
calculateTotal -> 3 seconds
the code looks like:
step1();
step2();
step3();
which is easier for us to understand.
In this example, async/await is used because each operation depends on the result of the previous operation. It makes the asynchronous workflow (Get User → Get Subscriptions → Calculate Total) easier to read, maintain, and handle errors compared to Promise chaining with .then().
References
https://www.geeksforgeeks.org/javascript/async-await-function-in-javascript/
https://www.w3schools.com/js/js_async_await.asp
Top comments (0)