Back to JavaScript
JavaScript
easy
mid

What kinds of operations can block JavaScript execution while running?

Synchronous code blocks the main thread until it finishes — long loops, big JSON.parse, sync XHR, alert/confirm/prompt, document.write, deep recursion. While blocked, no events, no rendering, no timers. Mitigate: break into chunks (yield to microtask/macrotask), use Web Workers for CPU, async APIs only, and avoid the listed blocking calls in production.

4 min read·~8 min to think through

JS is single-threaded. Anything synchronous on the main thread halts everything else — events queue up, rendering pauses, timers delay.

What blocks

CauseNotes
Long synchronous loopTight for over a million items, regex backtracking.
Big sync workJSON.parse(huge), JSON.stringify(huge), large structuredClone.
alert, confirm, promptBlocks JS and rendering until the user clicks.
document.write after parseForces a reflow; obsolete.
Synchronous XHRnew XMLHttpRequest(); xhr.open(..., false) — blocks until response. Removed/deprecated.
Sync localStorage on huge valueslocalStorage is synchronous API; large reads/writes stutter.
Deep recursionStack overflow possible.
while (true) / busy-wait loopsFamous footgun.

Symptoms

  • "Page Unresponsive" dialog.
  • Frozen UI; no scroll, no clicks, no animations.
  • Time-to-Interactive (TTI) regressions.
  • Bad INP scores.

Detection

  • Long Tasks APIPerformanceObserver reports tasks > 50ms.

``js new PerformanceObserver((list) => { for (const t of list.getEntries()) console.warn("long task", t); }).observe({ entryTypes: ["longtask"] }); ``

  • DevTools Performance panel shows main-thread task bars.

Mitigations

Yield to event loop

js
async function chunked(work) {
  let i = 0;
  while (i < work.length) {
    for (let j = 0; j < 1000 && i < work.length; j++) doOne(work[i++]);
    await new Promise(r => setTimeout(r));   // or scheduler.yield()
  }
}

Splits a long task into smaller ones; lets paints and events through.

React 18 transitions

startTransition(() => setLargeState(big)) marks updates as non-urgent; React can interrupt them.

Web Worker

js
const w = new Worker("parser.js");
w.postMessage(json);
w.onmessage = (e) => use(e.data);

Heavy compute (parsing, image processing, search indexing) lives on its own thread.

Streaming JSON parse

For big payloads, stream + parse line by line (ndjson) instead of single JSON.parse. Or use a streaming parser library.

Avoid blocking APIs

  • Never alert/confirm/prompt in production — use a custom modal.
  • Never sync XHR. Fetch is async.
  • Move heavy localStorage / IndexedDB work off the main thread.

Long sync work in React

  • useMemo for expensive derivations.
  • useDeferredValue for non-urgent renders.
  • startTransition for navigation / list updates.
  • Workers for CPU-heavy compute (e.g. PDF render, regex compile).

Interview framing

"JS is single-threaded; anything synchronous on the main thread blocks events, rendering, and timers. Common culprits: long loops, big JSON.parse, alert/confirm, sync XHR (deprecated), localStorage with large values, document.write. Detect with the Long Tasks API or DevTools. Mitigations: break long work into chunks with await + setTimeout, use React 18 transitions to defer non-urgent updates, move CPU-heavy work to a Web Worker. Avoid alert/confirm and sync XHR in production. The INP metric rewards apps that keep tasks under 50ms."

Follow-up questions

  • What is the Long Tasks API?
  • When would you use a Web Worker?
  • How does startTransition help?

Common mistakes

  • JSON.parse on a 50MB string.
  • alert/confirm in modern UIs.
  • Tight loops without yielding.

Performance considerations

  • Anything > 50ms hurts INP. Worker offload + chunking + transitions are the levers.

Edge cases

  • Microtask infinite loop (also blocks main thread).
  • Sync XHR still works in some legacy code.
  • Workers don't have DOM access.

Real-world examples

  • PDF.js workers, image processing in workers, big-list virtualization, INP optimizations.

Senior engineer discussion

Seniors instrument Long Tasks in production, identify the worst handlers, and either chunk, defer, or offload to workers.

Related questions