πŸŽ“ Velnov

🟨 JavaScript · Topic 19 of 20

Promises & async/await β€” JavaScript Questions with Answers

30 practice questions on Promises & async/await, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.

0 easy Β· 14 medium Β· 16 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.

Key concepts in this topic

PromisesAsyncPromise statesthenawaitcatchError handlingfinallyCleanupPromise constructorasyncReturn valuesModulesEvent loopPromise.allPerformanceConcurrencyallSettledPromise.raceTimeoutsPromise.anyChainingError propagationtry/catch

Jump to: Medium Β· Hard

Medium questions (14)

Q1. medium

What is a Promise?

  1. A An object representing a value that will be available later - a placeholder for an async result
  2. B A guaranteed return value
  3. C A type of callback
  4. D A loop construct

Answer: A β€” An object representing a value that will be available later - a placeholder for an async result

A promise is a receipt for future data. It lets you attach handlers now for a result that arrives later, avoiding deeply nested callbacks.

PromisesAsync

Q2. medium

What are the three states of a promise?

  1. A Pending, fulfilled, rejected
  2. B Start, middle, end
  3. C Open, closed, error
  4. D Waiting, running, done

Answer: A β€” Pending, fulfilled, rejected

A promise begins pending and settles exactly once into fulfilled (with a value) or rejected (with a reason). It can never change again.

Promise states

Q3. medium

How do you handle a promise's SUCCESS value?

fetch(url).then(res => res.json()).then(data => show(data));

const data = await (await fetch(url)).json();
  1. A .then(value => ...) or await
  2. B .catch(value => ...)
  3. C .finally(value => ...)
  4. D return value

Answer: A β€” .then(value => ...) or await

then receives the fulfilled value. await unwraps it more readably inside an async function.

thenawait

Q4. medium

How do you handle a promise REJECTION?

  1. A .catch(err => ...) or try/catch around await
  2. B .then(err => ...)
  3. C if (promise.error)
  4. D Rejections cannot be handled

Answer: A β€” .catch(err => ...) or try/catch around await

catch handles rejections anywhere earlier in the chain. With await, the rejection is thrown, so a normal try/catch works.

catchError handling

Q5. medium

What does .finally() do?

setLoading(true);
fetchData().then(show).catch(showError).finally(() => setLoading(false));
  1. A Runs whether the promise fulfilled or rejected - ideal for cleanup
  2. B Runs only on success
  3. C Runs only on failure
  4. D Ends the chain permanently

Answer: A β€” Runs whether the promise fulfilled or rejected - ideal for cleanup

Perfect for hiding a loading spinner or re-enabling a button. It receives no argument and passes the result through unchanged.

finallyCleanup

Q7. medium

What does an async function ALWAYS return?

async function f() { return 42; }
f().then(v => console.log(v));   // 42
console.log(f());                 // Promise { 42 }
  1. A A promise - even if you return a plain value
  2. B The value directly
  3. C undefined
  4. D A callback

Answer: A β€” A promise - even if you return a plain value

return 42 inside async produces a promise fulfilled with 42. That is why you must await it or use .then() at the call site.

asyncReturn values

Q8. medium

Where can you use the await keyword?

  1. A Inside an async function, or at the top level of an ES module
  2. B Anywhere
  3. C Only inside loops
  4. D Only in the browser

Answer: A β€” Inside an async function, or at the top level of an ES module

Using await in a regular function is a SyntaxError. Top-level await works in ES modules (type="module"), not in classic scripts.

awaitasyncModules

Q11. medium

What does Promise.all([p1, p2]) do?

  1. A Waits for ALL to fulfil and gives an array of results - but rejects immediately if ANY rejects
  2. B Waits for the first one
  3. C Runs them one after another
  4. D Ignores rejections

Answer: A β€” Waits for ALL to fulfil and gives an array of results - but rejects immediately if ANY rejects

It is all-or-nothing: one failure rejects the whole thing (the others still run but their results are discarded). Use allSettled when partial success is acceptable.

Promise.allConcurrency

Q15. medium

What does each .then() in a chain return?

fetch(url)
  .then(res => res.json())   // returns a promise - awaited
  .then(data => data.items)   // plain value
  .then(items => show(items));
  1. A A NEW promise resolved with the callback's return value - which is why chaining works
  2. B The original promise
  3. C undefined
  4. D The raw value

Answer: A β€” A NEW promise resolved with the callback's return value - which is why chaining works

Returning a value passes it to the next then; returning a PROMISE waits for it to settle first, flattening the chain automatically.

Chainingthen

Q18. medium

How do you catch an error from an awaited promise?

try {
  const data = await getData();
} catch (err) {
  showError(err);
}
  1. A Wrap the await in try/catch
  2. B Use .then only
  3. C Errors cannot be caught with await
  4. D Use if (error)

Answer: A β€” Wrap the await in try/catch

await converts rejection into a thrown error, so ordinary try/catch/finally works - one of the main readability wins of async/await.

try/catchawait

Q21. medium

How do you run async operations SEQUENTIALLY?

  1. A A for...of loop with await inside
  2. B forEach with await
  3. C Promise.all
  4. D map with await

Answer: A β€” A for...of loop with await inside

for...of respects await, pausing each iteration until the operation completes - necessary when each step depends on the previous or you must not overload a server.

for...ofSequential

Q23. medium

What does Promise.resolve(5) create?

  1. A A promise already fulfilled with 5
  2. B A pending promise
  3. C The number 5
  4. D A rejected promise

Answer: A β€” A promise already fulfilled with 5

Useful for returning a promise from a function that sometimes has a cached value, so callers can always use .then/await consistently.

Promise.resolve

Q26. medium

Why must you await response.json() after fetch?

const res = await fetch(url);
const data = await res.json();
  1. A Reading and parsing the body is itself asynchronous, so json() returns a promise
  2. B It is optional
  3. C To convert to a string
  4. D fetch is synchronous

Answer: A β€” Reading and parsing the body is itself asynchronous, so json() returns a promise

fetch resolves once the HEADERS arrive; the body may still be streaming. Hence the classic two awaits.

fetchjson

Q29. medium

Can a promise change state twice?

  1. A No - it settles once; later resolve/reject calls are ignored
  2. B Yes, any number of times
  3. C Only from rejected to fulfilled
  4. D Only with .then

Answer: A β€” No - it settles once; later resolve/reject calls are ignored

Immutability once settled makes promises predictable: every handler attached (before or after) sees the same single outcome.

Promise states

Hard questions (16)

Q6. hard

How do you create a promise manually?

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
  1. A new Promise((resolve, reject) => { ... })
  2. B Promise.create()
  3. C promise()
  4. D new Async()

Answer: A β€” new Promise((resolve, reject) => { ... })

The executor runs immediately; call resolve(value) on success or reject(error) on failure. Mainly used to wrap old callback APIs.

Promise constructor

Q9. hard

What is the output ORDER? async function f() { console.log("1"); await null; console.log("2"); } f(); console.log("3");

  1. A 1 3 2 - code before await runs synchronously; the rest resumes as a microtask
  2. B 1 2 3
  3. C 3 1 2
  4. D 1 3, then 2 never runs

Answer: A β€” 1 3 2 - code before await runs synchronously; the rest resumes as a microtask

An async function starts executing immediately and only pauses AT the first await, returning control to the caller. Awaiting even a non-promise defers the remainder.

asyncEvent loop

Q10. hard

What is wrong with this sequential code? const a = await fetchA(); const b = await fetchB();

const [a, b] = await Promise.all([fetchA(), fetchB()]);
  1. A If they are independent, this wastes time - B only starts after A finishes. Use Promise.all
  2. B It is a syntax error
  3. C await cannot be used twice
  4. D Nothing is wrong

Answer: A β€” If they are independent, this wastes time - B only starts after A finishes. Use Promise.all

Sequential awaits are correct when B needs A's result, but wasteful otherwise. Promise.all runs them concurrently, roughly halving the wait.

Promise.allPerformance

Q12. hard

How is Promise.allSettled different from Promise.all?

const results = await Promise.allSettled(promises);
results.forEach(r => r.status === "fulfilled" ? ok(r.value) : bad(r.reason));
  1. A It NEVER rejects - it waits for all and returns each result as {status, value|reason}
  2. B It is faster
  3. C It returns only successes
  4. D It stops at the first rejection

Answer: A β€” It NEVER rejects - it waits for all and returns each result as {status, value|reason}

Ideal when you want every outcome, e.g. uploading ten files and reporting which succeeded and which failed.

allSettled

Q13. hard

What does Promise.race([p1, p2]) return?

const timeout = ms => new Promise((_, rej) => setTimeout(() => rej(new Error("timeout")), ms));
await Promise.race([fetch(url), timeout(5000)]);
  1. A The result of whichever settles FIRST - fulfilled or rejected
  2. B The fastest successful one only
  3. C All results
  4. D The slowest one

Answer: A β€” The result of whichever settles FIRST - fulfilled or rejected

Commonly used for timeouts: race the real request against a promise that rejects after N seconds.

Promise.raceTimeouts

Q14. hard

What does Promise.any() do?

  1. A Fulfils with the FIRST successful promise, ignoring rejections (fails only if all fail)
  2. B Same as race
  3. C Same as all
  4. D Returns any random one

Answer: A β€” Fulfils with the FIRST successful promise, ignoring rejections (fails only if all fail)

Unlike race (which settles on the first result even if it is an error), any keeps waiting for a success - useful for querying several mirrors.

Promise.anyPromise.race

Q16. hard

What is the output? Promise.resolve(1) .then(v => { console.log(v); }) .then(v => console.log(v));

.then(v => { return v; })   // or just .then(v => v)
  1. A 1 then undefined - the first then returned nothing
  2. B 1 then 1
  3. C 1 only
  4. D undefined twice

Answer: A β€” 1 then undefined - the first then returned nothing

Forgetting to RETURN inside a then breaks the value chain - the next handler receives undefined. A very common bug.

ChainingReturn values

Q17. hard

Where does an error thrown inside a .then() go?

  1. A To the nearest .catch() LATER in the chain
  2. B To the surrounding try/catch
  3. C It is silently ignored
  4. D It crashes the browser

Answer: A β€” To the nearest .catch() LATER in the chain

Rejections skip subsequent then handlers until a catch is found. Note a catch placed BEFORE the throwing then cannot catch it - order matters.

Error propagationcatch

Q19. hard

What is an unhandled promise rejection?

  1. A A rejected promise with no catch handler - it logs a warning and can terminate Node processes
  2. B A promise that stays pending
  3. C A syntax error
  4. D A fulfilled promise

Answer: A β€” A rejected promise with no catch handler - it logs a warning and can terminate Node processes

Always end chains with .catch() or wrap awaits in try/catch. A global fallback: window.addEventListener('unhandledrejection', ...).

Error handlingNode.js

Q20. hard

What is wrong with using await inside forEach? items.forEach(async (i) => { await save(i); });

for (const i of items) await save(i);        // sequential
await Promise.all(items.map(i => save(i)));   // concurrent
  1. A forEach ignores the returned promises, so the code continues without waiting
  2. B It is a syntax error
  3. C async cannot be used in callbacks
  4. D Nothing is wrong

Answer: A β€” forEach ignores the returned promises, so the code continues without waiting

forEach discards return values, so nothing awaits the saves. Use a for...of loop for sequential work, or Promise.all(items.map(...)) for concurrent work.

  • A very common async bug in real projects.

forEachAsync loops

Q22. hard

What is the output? async function f() { throw new Error("boom"); } f().catch(e => console.log(e.message));

  1. A boom - throwing inside async REJECTS the returned promise
  2. B An uncaught error
  3. C Nothing
  4. D SyntaxError

Answer: A β€” boom - throwing inside async REJECTS the returned promise

Async functions convert throws into rejections, which is why try/catch and .catch() are interchangeable ways to handle them.

asyncRejection

Q24. hard

Can you await a NON-promise value? const x = await 5;

  1. A Yes - it is wrapped in a resolved promise, though it still defers the rest of the function
  2. B No, it throws
  3. C It returns undefined
  4. D It blocks forever

Answer: A β€” Yes - it is wrapped in a resolved promise, though it still defers the rest of the function

await accepts any value. This is handy when a function might return either a value or a promise - and it explains why 'await null' still yields to the event loop.

awaitThenable

Q25. hard

What is the output ORDER? console.log("A"); (async () => { console.log("B"); await 0; console.log("C"); })(); console.log("D");

  1. A A B D C
  2. B A B C D
  3. C A D B C
  4. D B A D C

Answer: A β€” A B D C

The async function body starts synchronously (B), pauses at await, control returns to the caller (D), then the continuation runs as a microtask (C).

asyncMicrotasks

Q27. hard

What is the promisify pattern?

const getPos = () => new Promise((res, rej) =>
  navigator.geolocation.getCurrentPosition(res, rej));
const pos = await getPos();
  1. A Wrapping a callback-based API in a promise so it can be awaited
  2. B Converting promises to callbacks
  3. C Making code synchronous
  4. D A testing technique

Answer: A β€” Wrapping a callback-based API in a promise so it can be awaited

Legacy APIs (older Node functions, geolocation, some libraries) take callbacks. Wrapping them once lets the rest of your code use async/await.

PromisifyLegacy APIs

Q28. hard

Does creating a promise start its work lazily or immediately?

  1. A Immediately - the executor runs as soon as the promise is created, even before .then is attached
  2. B Only when .then is called
  3. C Only when awaited
  4. D Never automatically

Answer: A β€” Immediately - the executor runs as soon as the promise is created, even before .then is attached

Promises are EAGER. const p = fetch(url) starts the request at once; awaiting later just waits for the already-running work. This is why Promise.all(fns.map(f => f())) runs concurrently.

Eager evaluation

Q30. hard

What is the practical difference between .then chains and async/await?

  1. A They are equivalent - await is syntax over promises, usually more readable for sequential logic
  2. B await is faster
  3. C then is deprecated
  4. D await avoids promises entirely

Answer: A β€” They are equivalent - await is syntax over promises, usually more readable for sequential logic

Use await for step-by-step flows and try/catch; use .then when composing pipelines or with combinators like Promise.all. Mixing both is fine.

async/awaitthen

Practice β€œPromises & async/await” as a quiz