Interview answer drill

Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.

When is Promise preferred over async/await in JavaScript?Frontend interview answer

HighIntermediateJavascript
Interview focus

This JavaScript interview question tests whether you can explain prefer Promise over async/await: concurrency and dedupe, connect it to production trade-offs, and handle common follow-up questions.

  • prefer Promise over async/await: concurrency and dedupe explanation without falling back to memorized docs wording
  • Promise and Async Await reasoning, edge cases, and production failure modes
  • How you would answer the most likely JavaScript interview follow-up
Practice more JavaScript interview questions
Interview quick answer

async/await improves readability, but Promise APIs are often better for composition, fan-out concurrency, and shared in-flight work. Strong answers show the accidental-serialization pitfall and when raw Promise style stays clearer.

Full interview answer

The core idea

async/await is usually best for readable step-by-step logic. But Promises are often better when you need composition, fan-out/fan-in concurrency, or shareable in-flight results. The common production pitfall is hiding independent work behind sequential await calls and accidentally adding latency.

Strong interview answer: it is not Promise vs async/await as enemies; async/await is built on Promises. You choose the style that best expresses the control flow.

Situation

Prefer

Why Promise style is stronger

Coordinate many async tasks

Promise.all/allSettled/any/race

Combinators express concurrency and outcome policy directly.

Share one in-flight request across callers

Store and reuse the same Promise

Avoid duplicate network calls and racey cache logic.

Need fan-out/fan-in orchestration

Return Promise composition

Makes parallel start + single join point obvious.

Library/middleware expects a Promise return

Return Promise chain directly

No extra wrapper code; keeps API surface simple.

Use async/await for readability, Promise APIs for composition-heavy flows.

Example 1: side-by-side concurrency decision

This is the easiest place to lose performance: the slow version reads clearly, but it serializes independent requests.

JAVASCRIPT
async function loadDashboardSlow(userId) {
  const user = await fetch(`/api/users/${userId}`).then((r) => r.json());
  const orders = await fetch(`/api/orders/${userId}`).then((r) => r.json());
  const recs = await fetch(`/api/recommendations/${userId}`).then((r) => r.json());
  return { user, orders, recs };
}

function loadDashboardFast(userId) {
  return Promise.all([
    fetch(`/api/users/${userId}`).then((r) => r.json()),
    fetch(`/api/orders/${userId}`).then((r) => r.json()),
    fetch(`/api/recommendations/${userId}`).then((r) => r.json())
  ]).then(([user, orders, recs]) => ({ user, orders, recs }));
}
                  

Example 2: in-flight dedupe cache (Promise is ideal)

A Promise can represent work already started. Multiple callers can await the same Promise safely, and a manual invalidation path keeps the cache story explicit.

JAVASCRIPT
const inFlight = new Map();

function getProduct(productId) {
  if (inFlight.has(productId)) return inFlight.get(productId);

  const p = fetch(`/api/products/${productId}`)
    .then((r) => {
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      return r.json();
    })
    .finally(() => inFlight.delete(productId));

  inFlight.set(productId, p);
  return p;
}

function invalidateProduct(productId) {
  inFlight.delete(productId);
}

Promise.all([getProduct('p1'), getProduct('p1')]).then(console.log);
                  

Example 3: avoid unnecessary async wrappers

If a function simply forwards another Promise chain, returning the Promise directly can be clearer because the boundary stays composition-friendly.

JAVASCRIPT
function fetchSettings(userId) {
  return fetch(`/api/settings/${userId}`).then((r) => r.json());
}

async function fetchSettings2(userId) {
  const res = await fetch(`/api/settings/${userId}`);
  return res.json();
}
                  

Rule of thumb

Use async/await when the main thing you are expressing is a story-like sequence of business steps. Use raw Promise style when the main thing you are expressing is the relationship between async tasks: start together, dedupe, race, join, or hand one in-flight result to multiple callers.

Common pitfall

Impact

Fix

Mixing styles randomly in one flow

Harder debugging and reviews

Choose one dominant style per function.

Using sequential await for independent calls

Unnecessary latency

Start tasks together and join with Promise.all.

Hiding shared in-flight work inside separate async functions

Duplicate requests and racey cache misses

Store and return the same Promise to all callers.

Most bugs come from the wrong control-flow shape, not from Promise itself.

Interview one-liner

Promise style is preferred when composing multiple concurrent operations, coordinating outcomes with combinators, or sharing in-flight asynchronous work across callers.

Practical scenario
A product page needs recommendations, inventory, and pricing from separate APIs. Running them sequentially with await adds unnecessary latency, while Promise combinators make fan-out/fan-in concurrency explicit. Meanwhile, product detail fetches may need one shared in-flight Promise so two widgets do not trigger duplicate requests.

Common pitfalls

  • Using await inside loops without checking if calls are independent.
  • Wrapping a Promise-returning utility in async even though the wrapper adds no clarity.
  • Ignoring invalidation for shared in-flight caches.
Trade-off or test tip
Test both fast-success and partial-failure cases. Add latency tests to confirm the refactor actually improves total response time, and test duplicate callers against one shared Promise path.

Still so complicated?

Use async/await when reading the logic like a story matters most. Use raw Promise APIs when coordinating many moving async pieces is the real challenge.

Similar questions
Guides
Preparing for interviews?

Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.