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?
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?
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?
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?
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?
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?
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?
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?
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?
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?
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.