Blocking operation
A blocking operation is a task that holds the single JavaScript thread and stops the rest of the code from running. While it lasts, the event loop waits, so the interface freezes, buttons do not respond, and animations and network requests are not processed.
Theory
TL;DR
- JavaScript runs on a single thread; the call stack can hold only one task at a time.
- Long synchronous code occupies the whole thread and every other task waits.
- The event loop cannot take anything from the queue until the stack is empty.
setTimeout(..., 0)does not save you: the callback queues up but cannot run during the block.- Fixes: split heavy work into chunks, move computation into Web Workers, and in Node.js use async APIs instead of the
*Syncones.
Quick example
console.log('A');
function block(ms) {
const start = Date.now();
while (Date.now() - start < ms) {}
}
block(3000); // block the thread for 3 seconds
console.log('B');Output:
A
(pause of 3 seconds)
BWhile the while loop runs, JavaScript can do nothing else: no clicks are handled, no timers fire, the interface is not repainted. That is blocking.
Why it happens
JavaScript runs in a single thread: at any moment the call stack can execute only one task.
When long running code lands there, it takes the whole thread, and every other task, including asynchronous ones, waits until it finishes. Even if you have a setTimeout scheduled, it will not run until the stack is free.
Schematically:
+----------------------+
| Call Stack | <- runs the blocking operation
| (busy for a long |
| time) |
+----------------------+
|
Event loop waits
Callback queue waitsNo asynchronous task can enter the stack until the blocking one is done.
What happens to asynchronous code during a block
console.log('1');
setTimeout(() => console.log('2'), 0);
const start = Date.now();
while (Date.now() - start < 3000) {} // blocking loop, 3 seconds
console.log('3');Output:
1
(pause of 3 seconds)
3
2setTimeout(..., 0) did not help: its callback reached the queue but could not run until the stack was freed after the while loop.
Typical blocking operations
| Operation | Why it blocks |
|---|---|
A long while / for | keeps the CPU busy |
| Heavy computation (recursion, sorting, cryptography) | blocks the thread |
alert(), prompt() | halt script execution |
sync versions of Node.js methods (fs.readFileSync) | wait for the result |
Long JSON conversions (JSON.stringify(hugeObject)) | run synchronously |
How to avoid blocking
Split large tasks into chunks (with setTimeout or requestIdleCallback):
function bigTask() {
for (let i = 0; i < 1e9; i++) {
if (i % 1e6 === 0) console.log(i);
}
}
setTimeout(bigTask, 0); // scheduled asynchronously, does not block the interfaceUse Web Workers for heavy computation on a separate thread:
// worker.js
onmessage = (e) => {
const result = e.data ** 2;
postMessage(result);
};In Node.js, use fs.promises instead of fs.readFileSync.
Summary
Imagine you have a single waiter (the JavaScript thread):
- Blocking code: the waiter stands at the stove waiting for a dish to cook and serves nobody else.
- Non blocking code: the waiter passes the order to the kitchen and moves to the next table.
JavaScript behaves like the second option. But if the waiter starts stirring the soup himself for ten minutes (CPU heavy code), service stops.
| Term | What it means |
|---|---|
| Blocking operation | a task that stops the rest of the code from running |
| Result | the event loop freezes, the interface stops responding |
| Examples | long loops, sync functions, alert(), heavy computation |
| How to avoid it | asynchronous APIs, Web Workers, splitting the task |
Common mistakes
- Believing
setTimeout(fn, 0)makes the code asynchronous "inside": it only defers the call, the function itself still blocks the thread. - Using
fs.readFileSyncinside an HTTP handler: one slow disk read stalls every request being served. - Serializing a huge object with
JSON.stringifyon the main thread instead of streaming it or moving it to a worker. - Confusing "a slow server request" with blocking: waiting on the network does not block the thread, computation does.
- Thinking
awaitfrees the thread from heavy synchronous code inside the function: after theawait, the code still runs on the main thread.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.