Async/Await in JavaScript: Writing Cleaner Asynchronous Code
Introduction
In the previous blog, we learned about promises and how they solve the problem of callback hell.
However, even promises can sometimes look complex when chaining multiple .then() calls.
To make asynchronous code even more readable and easier to write, JavaScript introduced:
Async/Await
Async/await allows us to write asynchronous code in a way that looks almost like synchronous code.
Why Async/Await Was Introduced
Promises improved callbacks, but they still have some drawbacks:
doTask()
.then((res) => {
return doNext(res);
})
.then((res) => {
return doAnother(res);
})
.then((final) => {
console.log(final);
})
.catch((err) => {
console.log(err);
});
Problems:
Still looks complex
Harder to read for beginners
Multiple
.then()chains
Async/await was introduced to:
Improve readability
Make code look synchronous
Simplify error handling
What is Async/Await?
Async/await is:
A syntactic sugar over promises that makes asynchronous code easier to read and write.
How Async Functions Work
An async function:
Always returns a promise
Can use the
awaitkeyword inside it
Example:
async function greet() {
return "Hello";
}
greet().then(console.log);
Output:
Hello
Even though we returned a string, it is wrapped inside a promise.
The Await Keyword
The await keyword:
Pauses the execution of an async function until the promise is resolved.
Example:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data received");
}, 2000);
});
}
async function getData() {
console.log("Start");
const data = await fetchData();
console.log(data);
console.log("End");
}
getData();
Output:
Start
Data received
End
Explanation:
awaitwaits for the promise to resolveCode looks synchronous but is asynchronous
Real-Life Analogy
Imagine you are cooking:
You start boiling water
You wait until it boils
Then you continue cooking
This "waiting" is like await, but without blocking the entire system.
Error Handling with Async/Await
With promises, we use .catch().
With async/await, we use try...catch.
Example:
async function fetchData() {
return new Promise((resolve, reject) => {
let success = false;
if (success) {
resolve("Data received");
} else {
reject("Error occurred");
}
});
}
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.log(error);
}
}
getData();
Benefit:
Cleaner error handling
Looks like synchronous try/catch
Promise vs Async/Await
Promise Style:
fetchData()
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err);
});
Async/Await Style:
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (err) {
console.log(err);
}
}
Key Differences
Promises use
.then()and.catch()Async/await uses
awaitandtry...catchAsync/await looks more readable and clean
Async Function Execution Flow (Concept)
Start → Call async function
→ await pauses inside function
→ Promise resolves
→ Execution resumes
→ End
Common Mistakes
Using
awaitoutside an async functionForgetting
try...catchNot handling rejected promises
Interview Points
Async/await is syntactic sugar over promises
asyncfunctions return promisesawaitpauses execution inside async functionBetter readability than promise chaining
Conclusion
Async/await makes asynchronous JavaScript:
Cleaner
More readable
Easier to manage
It is widely used in modern JavaScript, especially in backend development and API handling.