async/await in JavaScript

JavaScript

The short answer

async/await is a way to write asynchronous code that looks and behaves like synchronous code. It is built on top of promises but makes the code much easier to read and write.

How it works

Before async/await, we used .then() chains to handle promises. It worked, but when you had multiple asynchronous operations that depended on each other, the code became hard to follow.

Here is a simple example. Let's say you want to fetch a user and then fetch their orders.

With promises:

function getUserOrders(userId) {
return fetch(`/api/users/${userId}`)
.then((response) => response.json())
.then((user) => fetch(`/api/orders/${user.orderId}`))
.then((response) => response.json())
.then((order) => {
console.log(order);
});
}

With async/await:

async function getUserOrders(userId) {
const userResponse = await fetch(`/api/users/${userId}`);
const user = await userResponse.json();
const orderResponse = await fetch(
`/api/orders/${user.orderId}`
);
const order = await orderResponse.json();
console.log(order);
}

The second version reads top to bottom, just like synchronous code. Each await pauses the function until the promise resolves, then continues to the next line.

The async keyword

When you put async before a function, two things happen:

  1. The function always returns a promise. Even if you return a plain value, it gets wrapped in a promise automatically.
  2. You are now allowed to use the await keyword inside this function.
async function greet() {
return 'Hello';
}
// This is the same as
function greet() {
return Promise.resolve('Hello');
}
greet().then((message) => console.log(message)); // "Hello"

The await keyword

await pauses the execution of the async function until the promise it is waiting for resolves. It then returns the resolved value.

async function loadData() {
console.log('Start');
const data = await fetch('/api/data'); // pauses here
console.log('Done'); // runs after fetch completes
}

Here is the important part — await only pauses the function it is inside. It does not block the entire program. Other code outside this function can still run while this function is waiting.

Error handling

With promises, you use .catch(). With async/await, you use try...catch, which is the same pattern you already know from synchronous code.

async function getUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
const user = await response.json();
return user;
} catch (error) {
console.log('Something went wrong:', error);
}
}

Common Pitfalls

A common mistake candidates make is forgetting to handle errors with async/await. With .then() chains, you had .catch() at the end which was hard to miss. With async/await, if you do not use try...catch and the promise rejects, you get an unhandled promise rejection. Always wrap your await calls in try...catch when the operation can fail.

Common mistakes

Mistake 1: Using await in a loop when you could run things in parallel

// Slow — each request waits for the previous one
async function getUsers(ids) {
const users = [];
for (const id of ids) {
const user = await fetchUser(id);
users.push(user);
}
return users;
}
// Fast — all requests run at the same time
async function getUsers(ids) {
const users = await Promise.all(
ids.map((id) => fetchUser(id))
);
return users;
}

In the slow version, if each request takes 1 second and you have 5 users, it takes 5 seconds. In the fast version, it takes about 1 second because all requests run at the same time.

Mistake 2: Forgetting that async functions return promises

async function getData() {
return 42;
}
// This does not work
const result = getData();
console.log(result); // Promise { 42 }, not 42
// You need to await it or use .then()
const result = await getData(); // inside another async function
console.log(result); // 42

Interview Tip

When explaining async/await, start by showing the promise version first, then show the async/await version of the same code. This shows the interviewer you understand what async/await is built on top of and why it exists. Also mention Promise.all for running things in parallel — interviewers love to test if you know when to use await sequentially vs in parallel.

Why interviewers ask this

Almost every frontend application fetches data from APIs. Interviewers want to see if you understand how asynchronous code works in JavaScript, if you can handle errors properly, and if you know when to run things sequentially vs in parallel. A candidate who can explain async/await clearly and knows the common pitfalls shows they can write reliable, performant asynchronous code.