πŸŽ“ Velnov

🟨 JavaScript · Topic 18 of 20

Asynchronous JavaScript β€” JavaScript Questions with Answers

30 practice questions on Asynchronous JavaScript, 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

Single-threadedCall stackEvent loopsetTimeoutTimingTask queueMicrotasksMacrotasksOrderingCallbacksCallback hellPromisesNode.jssetIntervalclearIntervalBlockingPerformanceWeb WorkersThreadsStack traceError propagationAsync errorstry/catchAnimation

Jump to: Medium Β· Hard

Medium questions (14)

Q1. medium

What does 'JavaScript is single-threaded' mean?

  1. A It executes one statement at a time on one call stack - long tasks block everything
  2. B It can only run one file
  3. C It uses one CPU core for rendering
  4. D It cannot handle events

Answer: A β€” It executes one statement at a time on one call stack - long tasks block everything

There is one main thread, so a slow loop freezes the whole page including clicks and animations. Asynchronous APIs exist so waiting does not block that thread.

Single-threadedCall stack

Q2. medium

What is the output ORDER? console.log("A"); setTimeout(() => console.log("B"), 0); console.log("C");

  1. A A C B - the timer callback waits until the synchronous code finishes
  2. B A B C
  3. C B A C
  4. D A C, then B after a long delay

Answer: A β€” A C B - the timer callback waits until the synchronous code finishes

Even with 0 ms, the callback is queued and can only run once the call stack is empty. This is the clearest demonstration of the event loop.

Event loopsetTimeout

Q7. medium

What is a callback in asynchronous code?

  1. A A function you hand to an async operation, to be run when it finishes
  2. B A function that calls itself
  3. C A returned value
  4. D An error type

Answer: A β€” A function you hand to an async operation, to be run when it finishes

Rather than blocking to wait for a result, you say 'call this when done'. Timers, events and older APIs all use this pattern.

Callbacks

Q9. medium

What is the error-first callback convention?

  1. A The callback's FIRST parameter is an error (null when successful), the second is the data
  2. B Errors are thrown instead
  3. C The callback returns errors
  4. D There is no convention

Answer: A β€” The callback's FIRST parameter is an error (null when successful), the second is the data

Standard in Node.js: fs.readFile(path, (err, data) => { if (err) return handle(err); ... }). It forces callers to consider failure first.

Node.jsCallbacks

Q10. medium

What does setInterval do, and how do you stop it?

const id = setInterval(tick, 1000);
clearInterval(id);
  1. A Repeats a callback every N ms until clearInterval(id) is called
  2. B Runs once after N ms
  3. C Cannot be stopped
  4. D Pauses the page

Answer: A β€” Repeats a callback every N ms until clearInterval(id) is called

Always keep the returned id and clear it when done, or the interval keeps running (and leaking) after the component or page section is gone.

setIntervalclearInterval

Q13. medium

What is the call stack?

  1. A The list of functions currently executing - each call pushes a frame, each return pops one
  2. B A queue of events
  3. C Browser memory
  4. D The DOM tree

Answer: A β€” The list of functions currently executing - each call pushes a frame, each return pops one

Error stack traces are printouts of this stack. Overflowing it with runaway recursion gives 'Maximum call stack size exceeded'.

Call stackStack trace

Q16. medium

What does requestAnimationFrame do?

function loop() {
  move();
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
  1. A Schedules a callback to run just before the next repaint - ideal for smooth animation
  2. B Runs code every second
  3. C Loads images
  4. D Requests data from a server

Answer: A β€” Schedules a callback to run just before the next repaint - ideal for smooth animation

It syncs with the display refresh (about 60 fps) and pauses in background tabs, making it far better than setInterval for animation.

AnimationrAF

Q18. medium

Which of these are handled by Web APIs rather than the JS engine itself?

  1. A setTimeout, fetch, DOM events, geolocation
  2. B for loops and arithmetic
  3. C Array methods
  4. D String operations

Answer: A β€” setTimeout, fetch, DOM events, geolocation

The engine runs your code; the browser provides timers, networking and events. They do the waiting off-thread and queue callbacks when ready.

Web APIsRuntime

Q20. medium

What is the difference between synchronous and asynchronous code?

  1. A Synchronous blocks until it finishes; asynchronous starts an operation and continues, handling the result later
  2. B Async code is always faster
  3. C Sync code runs on another thread
  4. D There is no difference

Answer: A β€” Synchronous blocks until it finishes; asynchronous starts an operation and continues, handling the result later

Async does not mean parallel in JavaScript - it means 'do not block the thread while waiting'. The waiting happens elsewhere; your callback runs later on the same thread.

Concurrency

Q22. medium

What does queueMicrotask(fn) do?

  1. A Schedules fn in the microtask queue - it runs before timers but after current sync code
  2. B Runs fn immediately
  3. C Runs fn after 1 ms
  4. D Creates a Web Worker

Answer: A β€” Schedules fn in the microtask queue - it runs before timers but after current sync code

It gives the same priority as promise callbacks, useful for deferring work to just after the current task without waiting for a timer.

Microtasks

Q24. medium

How do you pause for 2 seconds in modern async code?

const sleep = ms => new Promise(r => setTimeout(r, ms));
await sleep(2000);
  1. A await new Promise(r => setTimeout(r, 2000))
  2. B sleep(2000)
  3. C wait(2)
  4. D thread.sleep(2000)

Answer: A β€” await new Promise(r => setTimeout(r, 2000))

JavaScript has no built-in sleep. Wrapping setTimeout in a promise gives a clean, non-blocking delay usable with await.

Promisesasync/await

Q26. medium

What does clearTimeout(id) do?

  1. A Cancels a pending timer before it fires
  2. B Stops all timers
  3. C Resets the clock
  4. D Nothing after the timer is set

Answer: A β€” Cancels a pending timer before it fires

Essential for debouncing: each new keystroke clears the previous pending timer so only the final one runs.

clearTimeoutDebounce

Q28. medium

Which pattern reads most clearly for sequential async steps today?

  1. A async/await with try/catch
  2. B Nested callbacks
  3. C Long .then() chains only
  4. D Synchronous XMLHttpRequest

Answer: A β€” async/await with try/catch

await makes asynchronous code read top-to-bottom like synchronous code, with familiar try/catch error handling - built on promises underneath.

async/awaitReadability

Q30. medium

Why does console.log show the OLD value here? let data = null; fetchData(d => data = d); console.log(data);

  1. A The callback has not run yet - the log executes before the async work completes
  2. B fetchData is broken
  3. C data is const
  4. D console.log is async

Answer: A β€” The callback has not run yet - the log executes before the async work completes

The single most common async misunderstanding. You must USE the data inside the callback (or await the promise) rather than reading it immediately after.

Async timingCommon mistakes

Hard questions (16)

Q3. hard

Does setTimeout(fn, 1000) guarantee the callback runs in exactly 1 second?

  1. A No - it runs after AT LEAST 1 second, once the stack is free
  2. B Yes, exactly
  3. C It runs immediately
  4. D It never runs

Answer: A β€” No - it runs after AT LEAST 1 second, once the stack is free

The delay is a minimum. If synchronous code is still running (or other callbacks are queued), the timer waits longer. Never rely on precise timing.

setTimeoutTiming

Q4. hard

What is the event loop?

  1. A The mechanism that moves queued callbacks onto the call stack whenever the stack is empty
  2. B A for loop over events
  3. C A browser animation
  4. D The DOM event system

Answer: A β€” The mechanism that moves queued callbacks onto the call stack whenever the stack is empty

Web APIs (timers, network) handle waiting off-thread and push their callbacks into a queue. The event loop constantly checks: is the stack empty? If so, take the next callback.

Event loopTask queue

Q5. hard

Which runs FIRST when the stack empties: a promise callback or a setTimeout callback?

setTimeout(() => console.log("timeout"));
Promise.resolve().then(() => console.log("promise"));
// promise, then timeout
  1. A The promise - MICROtasks have priority over macrotasks (timers)
  2. B setTimeout, because it was scheduled first
  3. C Whichever was written first
  4. D They run simultaneously

Answer: A β€” The promise - MICROtasks have priority over macrotasks (timers)

The microtask queue (promises, queueMicrotask) is fully drained before the next macrotask (setTimeout, events). This is why .then() consistently beats setTimeout(0).

MicrotasksMacrotasks

Q6. hard

What is the output order? console.log(1); setTimeout(() => console.log(2)); Promise.resolve().then(() => console.log(3)); console.log(4);

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

Answer: A β€” 1 4 3 2

Synchronous first (1, 4), then microtasks (3), then macrotasks (2). This exact question appears in countless interviews.

Event loopOrdering

Q8. hard

What is 'callback hell'?

getUser(id, (u) => {
  getOrders(u, (o) => {
    getItems(o, (i) => {
      // deeply nested...
    });
  });
});
  1. A Deeply nested callbacks for sequential async steps, hard to read and to error-handle
  2. B Too many functions in a file
  3. C A browser crash
  4. D Using callbacks at all

Answer: A β€” Deeply nested callbacks for sequential async steps, hard to read and to error-handle

Each step nests inside the previous one, drifting rightward (the 'pyramid of doom') with error handling duplicated at every level. Promises and async/await were created to flatten this.

Callback hellPromises

Q11. hard

Why can a long synchronous loop freeze the page?

  1. A It occupies the single thread, so rendering, clicks and timers cannot run until it finishes
  2. B It uses too much memory
  3. C The browser blocks loops
  4. D It does not freeze anything

Answer: A β€” It occupies the single thread, so rendering, clicks and timers cannot run until it finishes

The browser cannot repaint or process events while your code holds the thread. Break heavy work into chunks (setTimeout/requestIdleCallback) or move it to a Web Worker.

BlockingPerformance

Q12. hard

What is a Web Worker?

const w = new Worker("worker.js");
w.postMessage(data);
w.onmessage = (e) => console.log(e.data);
  1. A A script running on a SEPARATE thread, so heavy work does not block the UI
  2. B A server process
  3. C A type of callback
  4. D A browser extension

Answer: A β€” A script running on a SEPARATE thread, so heavy work does not block the UI

Workers communicate by messages and cannot touch the DOM, but they are ideal for parsing large files, image processing or heavy computation.

Web WorkersThreads

Q14. hard

What is the output? function a() { b(); } function b() { throw new Error("x"); } try { a(); } catch (e) { console.log("caught"); }

  1. A caught - the error propagates DOWN the call stack to the nearest try/catch
  2. B An uncaught error
  3. C Nothing
  4. D SyntaxError

Answer: A β€” caught - the error propagates DOWN the call stack to the nearest try/catch

Synchronous errors bubble through the stack until a try/catch handles them. Asynchronous callbacks run on an empty stack, which is why try/catch cannot catch them.

Error propagationCall stack

Q15. hard

Why does this NOT catch the error? try { setTimeout(() => { throw new Error("x"); }, 0); } catch (e) { console.log("caught"); }

  1. A The callback runs later on a fresh stack, long after the try block completed
  2. B setTimeout cannot throw
  3. C The syntax is wrong
  4. D It does catch it

Answer: A β€” The callback runs later on a fresh stack, long after the try block completed

try/catch is strictly synchronous. Move it inside the callback, or use promises with .catch()/await.

Async errorstry/catch

Q17. hard

What is the output order? setTimeout(() => console.log("t1"), 0); setTimeout(() => console.log("t2"), 0); Promise.resolve().then(() => console.log("p1")).then(() => console.log("p2"));

  1. A p1 p2 t1 t2 - ALL microtasks drain before any timer
  2. B t1 t2 p1 p2
  3. C p1 t1 p2 t2
  4. D t1 p1 t2 p2

Answer: A β€” p1 p2 t1 t2 - ALL microtasks drain before any timer

The chained .then also schedules a microtask, which runs in the same drain cycle - so both promise logs beat both timers.

MicrotasksEvent loop

Q19. hard

What is the output? console.log("start"); for (let i = 0; i < 3; i++) setTimeout(() => console.log(i), 0); console.log("end");

  1. A start end 0 1 2
  2. B start 0 1 2 end
  3. C start end 3 3 3
  4. D 0 1 2 start end

Answer: A β€” start end 0 1 2

Both logs run synchronously first; the three timer callbacks follow in order. let gives each its own i, so 0 1 2 (var would give 3 3 3).

Event loopClosures

Q21. hard

Why is nested async code better expressed with promises?

  1. A Promises flatten the nesting into a chain and centralise error handling in one .catch()
  2. B Promises are synchronous
  3. C Callbacks are unsupported
  4. D Promises are slower but prettier

Answer: A β€” Promises flatten the nesting into a chain and centralise error handling in one .catch()

Each callback level needed its own error check; a promise chain propagates rejections automatically to a single handler at the end.

PromisesCallback hell

Q23. hard

What happens if a microtask schedules another microtask endlessly?

  1. A The queue never empties, so the page freezes - timers and rendering never get a turn
  2. B The browser alternates fairly
  3. C It throws an error
  4. D Nothing happens

Answer: A β€” The queue never empties, so the page freezes - timers and rendering never get a turn

Microtasks are drained completely before anything else, so an infinite chain starves the event loop - worse than a long timer loop.

MicrotasksStarvation

Q25. hard

Why is a while loop the WRONG way to wait 2 seconds? while (Date.now() - start < 2000) { }

  1. A It blocks the single thread completely - the page freezes and nothing renders
  2. B It is not accurate
  3. C It uses too much memory
  4. D It works fine

Answer: A β€” It blocks the single thread completely - the page freezes and nothing renders

This 'busy wait' burns CPU and prevents all rendering and input. Always yield with a timer or promise instead.

BlockingBusy waiting

Q27. hard

What is the output? const start = Date.now(); setTimeout(() => console.log(Date.now() - start), 100); for (let i = 0; i < 1e9; i++) { }

  1. A A number much LARGER than 100 - the blocking loop delays the callback
  2. B Exactly 100
  3. C 0
  4. D Nothing is printed

Answer: A β€” A number much LARGER than 100 - the blocking loop delays the callback

The timer becomes ready at 100 ms but must wait for the stack to clear. This proves timer delays are minimums, not guarantees.

BlockingTimers

Q29. hard

Is async code parallel?

  1. A No - it is CONCURRENT: operations overlap in waiting, but JS callbacks still run one at a time on the main thread
  2. B Yes, fully parallel
  3. C Only with promises
  4. D Only in Node.js

Answer: A β€” No - it is CONCURRENT: operations overlap in waiting, but JS callbacks still run one at a time on the main thread

Several network requests can be in flight simultaneously (the browser handles them), but your JavaScript callbacks are processed sequentially. True parallel JS requires Web Workers.

Concurrency vs parallelism

Practice β€œAsynchronous JavaScript” as a quiz