JavaScript Promises: The Complete Interview Guide
The async pillar — the state machine, microtask timing, every combinator, concurrency shapes, cancellation, and the traps interviewers probe.
66 interview questions and coding challenges · 10 categories · Covers ES2025
Practice 66 JavaScript interview questions and coding problems with worked solutions, edge cases, and interviewer follow-ups. Start with language fundamentals, then build up to promise concurrency, DOM patterns, and machine-coding exercises.
These JavaScript interview questions and coding challenges cover recurring frontend and full-stack problems: closures, the event loop, debounce and throttle, Promise combinators, deep cloning, polyfills, DOM patterns, machine-coding tasks, and performance optimization — profiling, memory and garbage collection, reflow, and complexity trade-offs. Each challenge links to a worked solution with edge cases and interviewer follow-ups.
Comprehensive pillar guides that tie a whole topic together — read these first, then drill the individual questions below.
The async pillar — the state machine, microtask timing, every combinator, concurrency shapes, cancellation, and the traps interviewers probe.
How to reason about 'rebuild the standard library' questions from first principles — the recurring techniques, the call/apply/bind and JSON families, and where each deep-dive lives.
The modern built-ins interviews now expect — Object.groupBy, Promise.withResolvers, Set methods, and lazy iterator helpers — and how to deploy each under pressure.
Pick how much ground you need to cover. Each track curates the catalog into an ordered run and checks off what you finish.
About a month · ≈ 2 a day
Very-common plus common — the working majority of real interview rounds.
Weak on one theme? Drill it end to end — each area pulls the relevant questions from across all ten categories into a single ordered run.
Pick a theme to open an ordered run through it.
Categories are ordered as a ramp — each stage leans on the ones before it. Work top to bottom, or jump to wherever you left off.
The concepts every other question builds on. Interviewers probe these to see whether you understand how the language actually works, not just its syntax.
How the call stack, microtask queue, and macrotask queue decide execution order — with the output-prediction questions interviewers love.
What a closure really is, why loops with var trip people up, and how closures power memoization, once(), and module patterns.
The four binding rules, arrow-function behavior, and the lost-this bugs that call, apply, and bind exist to fix.
The prototype chain, __proto__ vs prototype, and what class syntax actually does under the hood.
Recent language features that are now fair game in interviews — and often the sanctioned replacement for utilities you used to hand-roll.
Object.groupBy, Promise.withResolvers, Set methods, and iterator helpers with lazy evaluation — the modern built-ins interviews now expect, and how to deploy them.
Implement groupBy from scratch, then meet the ES2024 built-ins — including the null-prototype result and Map.groupBy for object keys.
Rate-limiting user input and understanding JavaScript timers — among the most frequently asked practical frontend questions.
Implement debounce from scratch, with leading/trailing options and the classic search-input use case.
Implement throttle and know exactly when to reach for it instead of debounce (scroll, resize, mousemove).
Rebuild setTimeout on top of requestAnimationFrame to show you understand timer scheduling and drift.
Implement setInterval with setTimeout recursion — and fix the drift problems of the native version.
Track and clear every active timeout and interval — a utility question about monkey-patching globals safely.
The largest interview category: reimplement the Promise combinators, then compose them into retry, batching, and concurrency-control patterns used in real applications.
Implement a spec-faithful Promise with then chaining, state transitions, and async resolution.
Implement Promise.all: aggregate results in order, fail fast on the first rejection.
Implement allSettled: wait for every promise and report per-promise status objects.
Implement Promise.any with AggregateError semantics: first success wins, all failures reject.
Implement Promise.race and use it for the timeout pattern every senior interview touches.
Implement finally correctly: pass values through, and don't swallow rejections.
Run N async tasks with at most K in flight — the production-style p-limit pattern, including ordering and failure trade-offs.
Cancel fetch requests, add timeouts with AbortSignal.timeout, and write abortable async utilities.
Retry a failing async operation N times with backoff — a small function with big production implications.
Process a large list of async tasks in fixed-size sequential batches to protect downstream services.
The three concurrency shapes in one guide — sum vs slowest vs fastest, what 'parallel' means on one thread, and first-settle vs first-success.
Convert error-first callback APIs into promise-returning functions, like Node's util.promisify.
Cache in-flight and resolved requests to deduplicate API calls — with cache invalidation trade-offs.
Currying, composition, and the lodash utilities interviewers ask you to rebuild to test closure fluency.
Transform f(a, b, c) into f(a)(b)(c): the classic closure exercise, with arity handling.
The harder follow-up: support _ placeholders so arguments can arrive in any order.
Compose functions left-to-right into a pipeline — the one-liner with a lot of interview depth.
Pre-fill leading arguments of a function — partial application, and how it differs from currying.
Guarantee a function runs exactly once and returns its cached result forever after.
Cache function results by argument key — and discuss cache-key strategy and memory trade-offs.
A single-slot memoizer that remembers only the previous call — the pattern behind React's useMemo.
Deep equality, deep cloning, and array manipulation — questions that expose how well you understand references, recursion, and edge cases.
When to use the built-in structuredClone, where it fails (functions, prototypes), and how it compares to JSON round-tripping.
Recursively clone nested objects and arrays, handling cycles with a WeakMap.
Structural equality for nested data: type checks, key comparison, and recursion done right.
Flatten arbitrarily nested arrays recursively and iteratively — then compare with Array.prototype.flat.
Turn nested objects into dot-path keys ({ 'a.b.c': 1 }) and back — the transform behind form libraries and analytics events.
Use a Proxy to support arr[-1] like Python — a practical introduction to Proxy traps.
Rebuild the standard library. These questions verify you know what the built-ins actually do, including the edge cases.
Implement call and apply from scratch: the Symbol temp-key trick, null/primitive handling, and apply's array-like arguments.
Implement bind including partial application and the new-operator edge case most candidates miss.
Implement myNew(Constructor, ...args): prototype linking, this binding, and the return-object override rule.
Walk the prototype chain by hand, then meet Symbol.hasInstance — and learn where instanceof lies to you.
Copy enumerable own properties across sources, with getter evaluation and null-target errors.
The equality that fixes === for NaN and -0: tiny implementation, classic trivia follow-ups.
Reimplement typeof with Object.prototype.toString and learn why typeof null === 'object'.
Serialize values by hand: undefined, functions, cycles, and all the special cases JSON defines.
Write a small recursive-descent parser — the deepest polyfill question in the set.
Implement reduce including the no-initial-value case and empty-array TypeError.
Split source text into tokens — a warm-up for parsing questions like JSON.parse.
Event emitters, history, virtual DOM, and state management — the frontend-system questions that bridge JavaScript knowledge and framework internals.
Implement on, off, once, and emit — the pub/sub pattern behind Node streams and countless libraries.
Implement delegate(root, selector, handler) with closest() — one listener for a thousand rows, and why frameworks did exactly this.
Model back/forward/push navigation with an index and a stack — the core of every router.
Turn real DOM into a plain-object tree — the first half of understanding how React represents UI.
Rebuild real DOM from the virtual tree, completing the render pipeline.
Diff two virtual trees and apply minimal DOM mutations — the reconciliation step that makes the virtual DOM worth having.
Rebuild the classnames utility: strings, arrays, objects, and nested combinations.
A mini Redux store with Immer-style draft mutations — reducers, subscriptions, and immutability.
Small systems, not single functions: the 30–45 minute build-a-working-thing questions used to test composition, state, and browser API fluency.
O(1) get/put with least-recently-used eviction — the Map insertion-order trick, and the linked-list version interviewers ask about.
Debounce, cancellation, and stale-response guards composed into a search box that never shows the wrong results.
IntersectionObserver, in-flight guards, end-of-data states, and the sentinel pattern — the pagination question every feed team asks.
A dependency-free rating component: event delegation, hover preview vs committed state, keyboard support, and the ARIA pattern.
A concurrency-limited scheduler with priorities and cancellation — the pool question upgraded to the API-design round.
The senior differentiator: measure before you optimize, then reason about what's actually slow — algorithmic cost, memory and garbage collection, and the rendering pipeline. Interviewers use these to separate 'I know a faster trick' from 'I profile, fix the hot path, and prove the win.'
performance.now vs Date.now, the User Timing API, PerformanceObserver, DevTools flame charts, and the micro-benchmark traps that make numbers lie.
Big-O reasoning the way interviewers want it: the Map/Set/object/array cheat sheet, hidden O(n) costs like spread and includes, and trading memory for speed.
How GC reachability actually works, the four classic leaks, WeakMap/WeakRef, and finding retained memory with heap snapshots.
Why interleaving DOM reads and writes forces synchronous layout, the read/write batching fix, requestAnimationFrame, and compositor-only properties.
A hands-on exercise: profile first, fix the algorithm, hoist invariant work, cut allocations, memoize, then chunk off the main thread — in that order.
The open-ended, diagnosis-first questions senior and staff loops actually ask — where the signal is how you reason about production behavior under load, not whether you can recite an API.
A dashboard freezes while processing a large payload. How do you tell whether the cost is CPU work, DOM rendering, garbage collection, or the network?
Profiling & measuring performanceThe app leaks ~30 MB every time users navigate between two screens. How would you find and fix it?
Garbage collection & memory leaksA high-frequency input handler drops frames. When do you reach for debounce, throttle, requestAnimationFrame, or a Web Worker?
Layout thrashing & reflowA report over 50,000 rows blocks the main thread for seconds. Walk from the naive version to a responsive one.
Optimize a slow functionThe catalog prioritizes problems that reveal JavaScript behavior, implementation trade-offs, and edge-case reasoning—not syntax trivia. Difficulty reflects the reasoning and implementation depth required; interview-frequency labels are editorial estimates and should be used as a practice priority, not as an employer-specific guarantee.
JavaScript questions are one round. Compare the language and runtime trade-offs with the Java interview knowledge hub, connect the language fundamentals to the Angular interview knowledge hub, then pair them with system design deep dives and the Distributed Systems field manual for senior loops, or generate a personalized prep roadmap.