Introduction
Modern JavaScript has made asynchronous programming much easier and more readable with the introduction of async
and await
in ES2017 (ES8). These keywords are built on top of Promises and allow developers to write asynchronous code that looks and behaves like synchronous code.
If you’ve ever struggled with chained .then()
calls or callback hell, async/await
is the clean, readable solution you’ve been looking for.
What Are async
and await
?
async
: Declares a function as asynchronous, meaning it automatically returns a Promise.await
: Pauses the execution of theasync
function until the Promise is resolved or rejected.
Together, these allow you to write asynchronous code that reads almost like a story—top to bottom, left to right.
Basic Syntax
Example:
javascriptCopyEditasync function greet() {
return "Hello";
}
greet().then((message) => console.log(message)); // Output: Hello
Even though greet()
looks like a normal function, it returns a Promise because of the async
keyword.
Using await
The real power comes when you use await
to pause for a Promise:
javascriptCopyEditfunction delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
console.log("Start");
await delay(2000); // Waits for 2 seconds
console.log("End after 2 seconds");
}
run();
Output:
pgsqlCopyEditStart
(wait 2 seconds)
End after 2 seconds
The function waits for the Promise returned by delay()
to resolve before continuing.
Real-World Example: Fetching Data
Here’s how async/await
is used in a real application, such as fetching data from an API:
javascriptCopyEditasync function getUser() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error fetching user:", error);
}
}
getUser();
Explanation:
fetch
returns a Promise for the HTTP response.response.json()
also returns a Promise.- We
await
both to get the final user data. - Errors are handled with
try/catch
.
Why Use async/await
?
Benefits:
- Cleaner syntax than
.then()
chains - Easier error handling with
try/catch
- More readable and maintainable
- Works seamlessly with existing Promise-based APIs
Comparison:
With Promises:
javascriptCopyEditfetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
With async/await:
javascriptCopyEditasync function getData() {
try {
const response = await fetch(url);
const data = await response.json();
console.log(data);
} catch (err) {
console.error(err);
}
}
Both do the same thing, but the async/await
version is more readable.
Sequential vs. Parallel Execution
Sequential:
javascriptCopyEditasync function run() {
await task1();
await task2(); // Waits for task1 to finish first
}
Parallel (better performance):
javascriptCopyEditasync function run() {
const t1 = task1();
const t2 = task2();
await t1;
await t2;
}
If tasks are independent, start them without await
and then await
them together to improve performance.
Error Handling with try/catch
javascriptCopyEditasync function getData() {
try {
const res = await fetch("https://invalid-url");
const data = await res.json();
console.log(data);
} catch (error) {
console.error("Caught an error:", error);
}
}
Just like synchronous code, errors can be caught with try/catch
, making debugging easier.
Tips & Best Practices
- Use
async/await
only insideasync
functions. - Wrap your logic in
try/catch
blocks to handle errors. - Avoid using
await
in loops when possible—usePromise.all()
for parallelism. - Don’t block the main thread with long
await
chains unless necessary.
Conclusion
async/await
is one of the most powerful additions to JavaScript for writing cleaner, more readable asynchronous code. It builds on top of Promises but removes much of the complexity associated with chaining and nesting.
Summary:
async
turns a function into a Promise.await
pauses execution until the Promise resolves.- Use
try/catch
to handle errors. - It simplifies asynchronous logic significantly.
By mastering async/await
, you’ll write more efficient and maintainable JavaScript—whether you’re building APIs, UI apps, or working with databases.