PrepAhead
Start free
← All posts

JavaScript async and await quiz (10 questions)

June 6, 2026

  • JavaScript
  • Async
  • Full-stack

This set focuses on the async patterns interviewers care about most in JavaScript: what async and await really return, how errors flow, and when code is accidentally sequential or accidentally unfinished.

Once these questions feel natural, the next useful step is the event loop. That is usually where interviewers go when they want you to explain why asynchronous code behaves in a surprising order.

Question 1

What does an async function always return?

Pick an answer to see if you are correct
Reveal answer

Answer

A Promise - An async function always returns a Promise.

Explanation

Even if the function appears to return a plain value, JavaScript wraps it in a resolved Promise. If it throws, the returned Promise is rejected instead.

Common interview notes

A common follow-up is how this affects code that mixes async functions with older synchronous-looking APIs.

Question 2

What does await do when used with a Promise inside an async function?

Pick an answer to see if you are correct
Reveal answer

Answer

It pauses that async function until the Promise settles - await pauses the surrounding async function until the Promise settles.

Explanation

It does not freeze the whole runtime. Other work can continue while the async function is suspended, which is why await feels synchronous without actually blocking the event loop in the same way a long CPU task would.

Common interview notes

Strong answers usually mention that await is syntax on top of Promise-based behavior, not a separate concurrency model.

Question 3

Which pattern is best when two independent async requests can run at the same time and you need both results?

Pick an answer to see if you are correct
Reveal answer

Answer

Promise.all([requestA(), requestB()]) - Promise.all is the best default when independent async work can run concurrently and you need every result.

Explanation

Starting both Promises together avoids unnecessary sequential waiting. This is a common interview optimization point because many candidates accidentally serialize independent I/O with back-to-back awaits.

Example

const [user, orders] = await Promise.all([
  fetchUser(),
  fetchOrders(),
]);

Common interview notes

A useful follow-up is when Promise.all is the wrong choice because partial success is acceptable.

Question 4

What happens if an awaited Promise rejects and you do not catch the error inside the async function?

Pick an answer to see if you are correct
Reveal answer

Answer

The async function returns a rejected Promise - The async function returns a rejected Promise if the awaited operation rejects and the error is not caught.

Explanation

Inside async functions, thrown errors and rejected awaited Promises both flow through Promise rejection. That is why try/catch works naturally with await.

Common interview notes

Interviewers often ask you to compare error handling in async/await versus raw Promise chains.

Question 5

Which try/catch example correctly handles an awaited failure?

Pick an answer to see if you are correct
Reveal answer

Answer

try { await loadUser(); } catch (error) { handle(error); } - Wrapping the awaited call in try/catch is the correct async/await error-handling pattern.

Explanation

Once you use await inside the try block, rejections are surfaced as exceptions that can be caught in the matching catch block. Calling an async function without await does not let that surrounding try/catch catch the eventual rejection.

Common interview notes

A strong follow-up is to explain when you would intentionally return the Promise upward instead of catching locally.

Question 6

Why is using await inside a for loop sometimes a performance problem?

Pick an answer to see if you are correct
Reveal answer

Answer

It forces each iteration to wait for the previous one, which can serialize otherwise independent work - await inside a loop can serialize independent async operations and make the code slower than necessary.

Explanation

Sometimes sequential behavior is correct, but when each iteration is independent, collecting Promises first and then awaiting them together is often faster. Interviews often use this to test whether you can reason about concurrency versus sequence.

Common interview notes

A good answer mentions that correctness comes first, and some workflows do need strict sequential ordering.

Question 7

What is the main difference between Promise.all and Promise.allSettled?

Pick an answer to see if you are correct
Reveal answer

Answer

Promise.all rejects early on the first failure, while Promise.allSettled waits for every Promise and reports each outcome - Promise.all fails fast on the first rejection, while Promise.allSettled waits for all inputs and returns their individual statuses.

Explanation

This matters when your product can tolerate partial failure, such as loading several dashboard widgets independently. It is also a common interview question because it reveals whether the candidate chooses concurrency primitives based on business behavior.

Common interview notes

Strong answers include one realistic use case for each API rather than describing them only abstractly.

Question 8

What is wrong with using Array.forEach(async item => { await save(item); }) when you expect the outer function to wait for all saves?

Pick an answer to see if you are correct
Reveal answer

Answer

forEach does not await the async callbacks, so the outer flow can continue before the work finishes - forEach does not await async callbacks, so it is a common source of unfinished work and confusing control flow.

Explanation

If you need to wait for all operations, use a loop with await for sequence or map the items to Promises and use Promise.all for concurrency. This is one of the most common practical async interview traps.

Example

await Promise.all(items.map((item) => save(item)));

Common interview notes

A follow-up often asks the candidate to rewrite the snippet correctly for both sequential and concurrent requirements.

Question 9

Which statement about top-level await is most accurate?

Pick an answer to see if you are correct
Reveal answer

Answer

It can be used in module contexts that support it, not in every JavaScript file universally - Top-level await is available only in supported module contexts, not universally in every JavaScript script.

Explanation

Environment and module system details matter here, which is why interviews may use this question to test whether you understand the runtime context instead of memorizing syntax in isolation.

Common interview notes

Good answers stay careful about environment differences rather than over-claiming broad support rules.

Question 10

You need one request to happen only after another finishes because the second depends on the first result. What is the clearest approach?

Pick an answer to see if you are correct
Reveal answer

Answer

Use sequential await with the second request based on the first result - Sequential await is the clearest approach when the second operation depends on the first result.

Explanation

Not all async work should be parallelized. In interviews, a strong answer shows that you can distinguish true dependencies from accidentally serialized independent work.

Example

const user = await fetchUser();
const profile = await fetchProfile(user.id);

Common interview notes

A useful follow-up is to ask the candidate to identify which lines in a mixed workflow can run concurrently and which cannot.

Full answer key

Review every answer in one place, with explanations and interview tips below.

1. What does an async function always return?

Answer summary

A Promise — An async function always returns a Promise.

Even if the function appears to return a plain value, JavaScript wraps it in a resolved Promise. If it throws, the returned Promise is rejected instead.

Interview tip: A common follow-up is how this affects code that mixes async functions with older synchronous-looking APIs.

2. What does await do when used with a Promise inside an async function?

Answer summary

It pauses that async function until the Promise settles — await pauses the surrounding async function until the Promise settles.

It does not freeze the whole runtime. Other work can continue while the async function is suspended, which is why await feels synchronous without actually blocking the event loop in the same way a long CPU task would.

Interview tip: Strong answers usually mention that await is syntax on top of Promise-based behavior, not a separate concurrency model.

3. Which pattern is best when two independent async requests can run at the same time and you need both results?

Answer summary

Promise.all([requestA(), requestB()]) — Promise.all is the best default when independent async work can run concurrently and you need every result.

Starting both Promises together avoids unnecessary sequential waiting. This is a common interview optimization point because many candidates accidentally serialize independent I/O with back-to-back awaits.

const [user, orders] = await Promise.all([
  fetchUser(),
  fetchOrders(),
]);

Interview tip: A useful follow-up is when Promise.all is the wrong choice because partial success is acceptable.

4. What happens if an awaited Promise rejects and you do not catch the error inside the async function?

Answer summary

The async function returns a rejected Promise — The async function returns a rejected Promise if the awaited operation rejects and the error is not caught.

Inside async functions, thrown errors and rejected awaited Promises both flow through Promise rejection. That is why try/catch works naturally with await.

Interview tip: Interviewers often ask you to compare error handling in async/await versus raw Promise chains.

5. Which try/catch example correctly handles an awaited failure?

Answer summary

try { await loadUser(); } catch (error) { handle(error); } — Wrapping the awaited call in try/catch is the correct async/await error-handling pattern.

Once you use await inside the try block, rejections are surfaced as exceptions that can be caught in the matching catch block. Calling an async function without await does not let that surrounding try/catch catch the eventual rejection.

Interview tip: A strong follow-up is to explain when you would intentionally return the Promise upward instead of catching locally.

6. Why is using await inside a for loop sometimes a performance problem?

Answer summary

It forces each iteration to wait for the previous one, which can serialize otherwise independent work — await inside a loop can serialize independent async operations and make the code slower than necessary.

Sometimes sequential behavior is correct, but when each iteration is independent, collecting Promises first and then awaiting them together is often faster. Interviews often use this to test whether you can reason about concurrency versus sequence.

Interview tip: A good answer mentions that correctness comes first, and some workflows do need strict sequential ordering.

7. What is the main difference between Promise.all and Promise.allSettled?

Answer summary

Promise.all rejects early on the first failure, while Promise.allSettled waits for every Promise and reports each outcome — Promise.all fails fast on the first rejection, while Promise.allSettled waits for all inputs and returns their individual statuses.

This matters when your product can tolerate partial failure, such as loading several dashboard widgets independently. It is also a common interview question because it reveals whether the candidate chooses concurrency primitives based on business behavior.

Interview tip: Strong answers include one realistic use case for each API rather than describing them only abstractly.

8. What is wrong with using Array.forEach(async item => { await save(item); }) when you expect the outer function to wait for all saves?

Answer summary

forEach does not await the async callbacks, so the outer flow can continue before the work finishes — forEach does not await async callbacks, so it is a common source of unfinished work and confusing control flow.

If you need to wait for all operations, use a loop with await for sequence or map the items to Promises and use Promise.all for concurrency. This is one of the most common practical async interview traps.

await Promise.all(items.map((item) => save(item)));

Interview tip: A follow-up often asks the candidate to rewrite the snippet correctly for both sequential and concurrent requirements.

9. Which statement about top-level await is most accurate?

Answer summary

It can be used in module contexts that support it, not in every JavaScript file universally — Top-level await is available only in supported module contexts, not universally in every JavaScript script.

Environment and module system details matter here, which is why interviews may use this question to test whether you understand the runtime context instead of memorizing syntax in isolation.

Interview tip: Good answers stay careful about environment differences rather than over-claiming broad support rules.

10. You need one request to happen only after another finishes because the second depends on the first result. What is the clearest approach?

Answer summary

Use sequential await with the second request based on the first result — Sequential await is the clearest approach when the second operation depends on the first result.

Not all async work should be parallelized. In interviews, a strong answer shows that you can distinguish true dependencies from accidentally serialized independent work.

const user = await fetchUser();
const profile = await fetchProfile(user.id);

Interview tip: A useful follow-up is to ask the candidate to identify which lines in a mixed workflow can run concurrently and which cannot.

Try each question on your own, then open "Reveal answer" for the full write-up. For tailored practice and Check feedback on open-ended responses, use PrepAhead in the app - not on blog pages.