AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

08 Asynchronous JavaScript / Checkpoint

Checkpoint — Asynchronous JavaScript

25 min · +25 XP · 3 exercises · 12 questions

Exercises0/3
Quiz · 70% to clear12 q

This checkpoint covers the event loop (one thread, tasks versus microtasks, nextTick, Node's phases), error-first callbacks, promise states and the chaining rules, async/await semantics (sequential versus concurrent, return await, floating promises, races across await), the four combinators, bounded concurrency, timeouts and AbortController, async iteration, and timers with debounce/throttle.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • The order of sync code, process.nextTick, Promise.then, setTimeout(0); why a recursive microtask starves the loop.
  • What then returns and what happens when a handler returns a value, a promise, or throws; what an unhandled rejection does in Node.
  • Why await in a loop is sequential; how to run independent work concurrently; why forEach(async) is wrong; when return await matters.
  • all versus allSettled versus race versus any; how a concurrency pool works; how a timeout and a cancellation are built.
  • Debounce versus throttle; setInterval versus recursive setTimeout; what keeps a Node process alive.

The programs are a dependency-aware job scheduler that starts each job when its prerequisites finish, a fetch pipeline with retry, backoff, timeout and per-item outcomes, and an async queue with waiting consumers.

Common questions

In what order do sync code, process.nextTick, Promise.then and setTimeout(0) run?

Synchronous code first, then process.nextTick callbacks, then promise reactions such as .then, then the setTimeout(0) callback. Every pending microtask runs before the event loop takes its next task, and a timer callback is a task.

Why is await inside a loop sequential?

Each await pauses the function until that one promise settles, so the next iteration's operation does not start until the previous one has finished. To run independent operations concurrently, map the items to promises first and await Promise.all over them.

What is the difference between Promise.race and Promise.any?

Promise.race settles as soon as the first input settles, so an early rejection wins. Promise.any waits for the first input to fulfil, ignoring rejections, and rejects with an AggregateError only if every input rejects.

Async JavaScript Quiz: Event Loop, Promises and Async/Await

Test asynchronous JavaScript with 12 questions and three programs: the event loop, promise chaining, async/await, Promise.all and race, timeouts, debounce.

  • Course: JavaScript study plan
  • Module: Asynchronous JavaScript
  • Kind: Checkpoint — cleared at 70%
  • Reading time: 25 min
  • Runtime: Node 16

Checkpoint — Asynchronous JavaScript is the checkpoint that closes the Asynchronous JavaScript module: a graded quiz and whole-program exercises, passed at 70%.

Instructions

This checkpoint covers the event loop (one thread, tasks versus microtasks, nextTick, Node's phases), error-first callbacks, promise states and the chaining rules, async/await semantics (sequential versus concurrent, return await, floating promises, races across await), the four combinators, bounded concurrency, timeouts and AbortController, async iteration, and timers with debounce/throttle.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • The order of sync code, process.nextTick, Promise.then, setTimeout(0); why a recursive microtask starves the loop.
  • What then returns and what happens when a handler returns a value, a promise, or throws; what an unhandled rejection does in Node.
  • Why await in a loop is sequential; how to run independent work concurrently; why forEach(async) is wrong; when return await matters.
  • all versus allSettled versus race versus any; how a concurrency pool works; how a timeout and a cancellation are built.
  • Debounce versus throttle; setInterval versus recursive setTimeout; what keeps a Node process alive.

The programs are a dependency-aware job scheduler that starts each job when its prerequisites finish, a fetch pipeline with retry, backoff, timeout and per-item outcomes, and an async queue with waiting consumers.

Common questions

In what order do sync code, process.nextTick, Promise.then and setTimeout(0) run?

Synchronous code first, then process.nextTick callbacks, then promise reactions such as .then, then the setTimeout(0) callback. Every pending microtask runs before the event loop takes its next task, and a timer callback is a task.

Why is await inside a loop sequential?

Each await pauses the function until that one promise settles, so the next iteration's operation does not start until the previous one has finished. To run independent operations concurrently, map the items to promises first and await Promise.all over them.

What is the difference between Promise.race and Promise.any?

Promise.race settles as soon as the first input settles, so an early rejection wins. Promise.any waits for the first input to fulfil, ignoring rejections, and rejects with an AggregateError only if every input rejects.

Exercises

A dependency-aware job scheduler

Each line is a job name ms deps where deps is a comma list of job names or -. Write a memoised promiseFor(name): it waits for every dependency's promise, then await sleep(ms), records the completion order, and resolves with { finish } — a virtual finish time equal to the latest dependency finish plus ms. Start every job, wait for all, and print order: <completion order>, finish: <name=finish ...> (input order) and makespan=<max finish>.

Example: a 20 -, b 40 -, c 10 a, d 10 a,b →

order: a c b d
finish: a=20 b=40 c=30 d=50
makespan=50

c starts as soon as a is done; d must wait for b too.

A fetch pipeline with retry, backoff and timeout

The starter's fakeFetch(spec) takes ms and fails with a TransientError for its first failures calls. Write withTimeout(promise, ms) (race + timer, cleared in finally, Error("timed out after <ms> ms")) and retry(fn, { attempts, isTransient }) that retries transient failures with a backoff of 2^(i-1) ms and otherwise throws Error("gave up after <i> attempts", { cause }). Line 1 is attempts timeoutMs; each following line is url ms failures. Run every url through retry(() => withTimeout(fakeFetch(spec), timeoutMs)) with Promise.allSettled and print, in input order, <url>: ok after <n> attempt(s) or <url>: failed - <message> <- <cause name>: <cause message>, then summary: ok=<n> failed=<n>.

Example: 3 50, u1 5 0, u2 5 2, u3 5 5, u4 100 0 →

u1: ok after 1 attempt(s)
u2: ok after 3 attempt(s)
u3: failed - gave up after 3 attempts <- TransientError: u3 attempt 3 failed
u4: failed - gave up after 1 attempts <- Error: timed out after 50 ms
summary: ok=2 failed=2

An async queue with waiting consumers

Implement AsyncQueue with a private items array and a private list of waiting resolvers: put(value) hands the value straight to the oldest waiting consumer if there is one, otherwise stores it; take() returns a promise — resolved immediately when an item is available, otherwise pending until a put; get size and get waiting. Commands: take <consumer> (the consumer prints <consumer> got <value> when its promise resolves), put <value>, status (prints size=<items> waiting=<consumers>). After every command await null so the pending then callbacks print before the next command runs.

Example: take c1, take c2, status, put apple, put pear, status, put fig, status, take c3, status →

size=0 waiting=2
c1 got apple
c2 got pear
size=0 waiting=0
size=1 waiting=0
c3 got fig
size=0 waiting=0

In this module: Asynchronous JavaScript

← Timers and scheduling — setTimeout, setInterval, nextTick, and debounce/throttle · CommonJS and ES modules — two module systems, one runtime →