Skip to main content

Блокуюча операція

Коротко

Коли в JavaScript відбувається блокуюча операція, event loop (цикл подій) чекає, поки вона закінчиться, а отже, весь інтерфейс "зависає", кнопки не натискаються, анімації та мережеві запити не обробляються.

Приклад блокуючої операції

javascript
console.log('A'); function block(ms) { const start = Date.now(); while (Date.now() - start < ms) {} } block(3000); // блокуємо потік на 3 секунди console.log('B');

Вивід:

javascript
A (пауза 3 секунди) B

Поки виконується while, JS не може робити нічого іншого: не обробляти кліки, не запускати таймери, не оновлювати інтерфейс. Це і є blocking.

Чому це відбувається

JavaScript працює в одному потоці (single thread): в один момент часу в Call Stack (стеку викликів) може виконуватися лише одна задача.

Коли туди потрапляє довгий код, він займає весь потік, і решта задач (зокрема асинхронні) чекають, поки він закінчиться.

Навіть якщо у тебе є setTimeout, він не виконається, поки стек не звільниться.

Візуально

javascript
┌──────────────────────┐ │ Call Stack │ ← виконує блокуючу операцію │ (зайнятий надовго) │ └──────────────────────┘ ↓ Event Loop чекає Черга колбеків чекає

Жодна асинхронна задача не може потрапити в стек, поки блокуюча не завершиться.

Приклади типових блокуючих операцій у JS

ОпераціяЧому блокує
Довгий while / forзаймає процесор
Великі обчислення (рекурсія, сортування, криптографія)блокує потік
alert(), prompt()зупиняє виконання скрипту
sync-версії методів Node.js (fs.readFileSync)чекають результат
Довгі JSON-перетворення (JSON.stringify(величезний_об'єкт))виконуються синхронно

Що відбувається з асинхронним кодом при блокуванні

javascript
console.log('1'); setTimeout(() => console.log('2'), 0); const start = Date.now(); while (Date.now() - start < 3000) {} // блокуючий цикл 3 сек console.log('3');

Вивід:

javascript
1 (пауза 3 секунди) 3 2

setTimeout(..., 0) не допоміг: його колбек потрапив у чергу, але не міг виконатися, поки стек не звільнився після while.

Як уникнути блокування

Розбивати великі задачі на частини (через setTimeout / requestIdleCallback):

javascript
function bigTask() { for (let i = 0; i < 1e9; i++) { if (i % 1e6 === 0) console.log(i); } } setTimeout(bigTask, 0); // виконується асинхронно, не блокуючи інтерфейс

Використовувати Web Workers - для важких обчислень в окремому потоці:

javascript
// 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, розділення задач

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.