Блокуюча операція
Коротко
Коли в JavaScript відбувається блокуюча операція, event loop (цикл подій) чекає, поки вона закінчиться, а отже, весь інтерфейс "зависає", кнопки не натискаються, анімації та мережеві запити не обробляються.
Приклад блокуючої операції
console.log('A');
function block(ms) {
const start = Date.now();
while (Date.now() - start < ms) {}
}
block(3000); // блокуємо потік на 3 секунди
console.log('B');Вивід:
A
(пауза 3 секунди)
BПоки виконується while,
JS не може робити нічого іншого:
не обробляти кліки, не запускати таймери, не оновлювати інтерфейс.
Це і є blocking.
Чому це відбувається
JavaScript працює в одному потоці (single thread): в один момент часу в Call Stack (стеку викликів) може виконуватися лише одна задача.
Коли туди потрапляє довгий код, він займає весь потік, і решта задач (зокрема асинхронні) чекають, поки він закінчиться.
Навіть якщо у тебе є setTimeout, він не виконається,
поки стек не звільниться.
Візуально
┌──────────────────────┐
│ Call Stack │ ← виконує блокуючу операцію
│ (зайнятий надовго) │
└──────────────────────┘
↓
Event Loop чекає
Черга колбеків чекаєЖодна асинхронна задача не може потрапити в стек, поки блокуюча не завершиться.
Приклади типових блокуючих операцій у JS
| Операція | Чому блокує |
|---|---|
Довгий while / for | займає процесор |
| Великі обчислення (рекурсія, сортування, криптографія) | блокує потік |
alert(), prompt() | зупиняє виконання скрипту |
sync-версії методів Node.js (fs.readFileSync) | чекають результат |
Довгі JSON-перетворення (JSON.stringify(величезний_об'єкт)) | виконуються синхронно |
Що відбувається з асинхронним кодом при блокуванні
console.log('1');
setTimeout(() => console.log('2'), 0);
const start = Date.now();
while (Date.now() - start < 3000) {} // блокуючий цикл 3 сек
console.log('3');Вивід:
1
(пауза 3 секунди)
3
2setTimeout(..., 0) не допоміг:
його колбек потрапив у чергу,
але не міг виконатися,
поки стек не звільнився після while.
Як уникнути блокування
Розбивати великі задачі на частини (через setTimeout / requestIdleCallback):
function bigTask() {
for (let i = 0; i < 1e9; i++) {
if (i % 1e6 === 0) console.log(i);
}
}
setTimeout(bigTask, 0); // виконується асинхронно, не блокуючи інтерфейсВикористовувати Web Workers - для важких обчислень в окремому потоці:
// worker.js
onmessage = (e) => {
const result = e.data ** 2;
postMessage(result);
};У Node.js - використовувати fs.promises замість fs.readFileSync.
Приклад з життя
Уяви, що у тебе один офіціант (JS потік):
- Блокуючий код - офіціант чекає, поки приготується страва, і не обслуговує інших.
- Неблокуючий - він передає замовлення на кухню і йде обслуговувати наступний стіл.
JavaScript - як другий варіант. Але якщо офіціант сам почне "заважати суп" протягом 10 хвилин (CPU-важкий код), все, обслуговування зупиниться.
Підсумок
| Термін | Що означає |
|---|---|
| Блокуюча операція | Задача, яка зупиняє виконання решти коду |
| Результат | Event loop "заморожується", UI не реагує |
| Приклади | Довгі цикли, sync-функції, alert(), великі обчислення |
| Як уникнути | Асинхронні API, Web Workers, розділення задач |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.