async/await is syntax sugar built directly on top of Promises — it doesn't replace them, it just gives you a cleaner way to write and read Promise-based code, making asynchronous logic look almost exactly like ordinary, top-to-bottom synchronous code.
The async Keyword
Adding async before a function declaration does two things: it makes the function always return a Promise, and it unlocks the ability to use await inside it.
async function greet() {
return "Hello";
}
greet().then((result) => console.log(result));
Output:
Hello
Even though greet() just returns a plain string, wrapping it in async automatically wraps that return value in a resolved Promise — that's why calling .then() on it works.
The await Keyword
await pauses execution of the async function (not the whole program) until the Promise it's waiting on settles, then gives you back the resolved value directly — no .then() needed.
function wait(ms, value) {
return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}
async function run() {
console.log("Start");
const first = await wait(300, "first result");
console.log(first);
const second = await wait(300, "second result");
console.log(second);
console.log("Done");
}
run();
Output:
Start
first result
second result
Done
Compare this to the equivalent .then() chain — each step here reads as a plain, sequential line of code instead of a nested callback or chained .then().
Error Handling with try...catch
Since await makes an async function look synchronous, you handle its errors the exact same way you would in regular synchronous code: with try...catch, instead of a Promise's .catch().
function fetchData(shouldFail) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) reject(new Error("Network error"));
else resolve({ id: 1, name: "Item" });
}, 200);
});
}
async function loadData() {
try {
const data = await fetchData(true);
console.log(data);
} catch (err) {
console.log("Caught:", err.message);
}
}
loadData();
Output:
Caught: Network error
A common beginner mistake is using await outside of an async function (it's a syntax error, except at the top level of a module), or forgetting await entirely and logging the Promise object itself instead of its resolved value. In modern JavaScript, async/await combined with the Fetch API is the standard way to work with network requests.
