Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Блокування event loop». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**JavaScript однопотоковий: у кожен момент часу виконується лише одна інструкція, тому довга синхронна операція зупиняє event loop і разом із ним геть усе, що чекає в черзі.** Поки крутиться важкий цикл, браузер не реагує на кліки, скрол і ввід, не малює кадри, не запускає `setTimeout`, `fetch`-колбеки й `.then()` промісів, а інтерфейс просто «висне». На сервері Node.js ефект гірший: CPU-важка задача в одному запиті ставить у чергу всі інші запити, і сервер перестає відповідати. Рішення: розбивати обчислення на частини (chunking) і віддавати керування event loop, виносити важке в Web Workers або Worker Threads, і ніколи не брати синхронні API вводу-виводу. ```javascript console.log('Start'); for (let i = 0; i < 1e9; i++) {} // blocks the event loop console.log('End'); ``` **Ключове:** блокуючий синхронний код заморожує весь застосунок, бо потік один; важкі обчислення виносять у воркери або ділять на чанки.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Блокування event loop, це ситуація, коли JavaScript виконує довгу синхронну операцію, і доки вона не завершиться, жодна інша подія не обробляється.** Мова однопотокова, тому важкий цикл чи синхронне читання файлу зупиняють і рендеринг, і таймери, і проміси, і мережеві колбеки. ## Теорія ### TL;DR - Event loop послідовно виконує задачі: колбеки, проміси, таймери, події. - JavaScript однопотоковий, у кожен момент часу виконується лише одна інструкція. - Довга синхронна операція означає, що все інше стоїть у черзі й чекає. - У браузері це заморожений UI: немає реакції на кліки, скрол і ввід. - У Node.js це сервер, який не відповідає, бо всі запити стоять за однією CPU-важкою задачею. - Ліки: chunking, Web Workers, Worker Threads або `child_process`, і асинхронні API замість синхронних. ### Швидкий приклад ```javascript console.log('Start'); for (let i = 0; i < 1e9; i++) {} // blocks the event loop console.log('End'); ``` Поки йде цей цикл: - браузер не реагує на кліки, скрол, ввід; - не виконуються таймери й проміси; - UI «висить». ### Що таке event loop Event loop, це механізм, який: - послідовно виконує задачі (колбеки, проміси, таймери, події); - обробляє асинхронні операції; - відповідає за реакцію інтерфейсу та відгук застосунку. > JavaScript однопотокова мова: у кожен момент часу виконується тільки одна інструкція. Якщо щось виконується довго, все інше стоїть у черзі й чекає. ### Чому це погано #### 1. Зависання інтерфейсу Користувач не може взаємодіяти із сайтом: кнопки, поля вводу, анімації, усе «заморожено». #### 2. Асинхронні операції не виконуються Ані `setTimeout`, ані `fetch`, ані `Promise.then` не запустяться, доки блокування не закінчиться. ```javascript setTimeout(() => console.log('1s elapsed'), 1000); const end = Date.now() + 5000; while (Date.now() < end) {} // blocks for 5 seconds ``` Результат: ```text (after 5 seconds) 1s elapsed ``` Таймер виконався із запізненням: колбек потрапив у чергу вчасно, але черга не оброблялася. #### 3. Втрата продуктивності в Node.js Якщо на сервері Node.js виконується CPU-важка задача (наприклад, парсинг великого JSON, шифрування тощо), решта запитів стане в чергу, і сервер перестане відповідати. ### Як уникнути блокування 1. **Діліть обчислення на частини (chunking):** ```javascript function heavyTask() { let i = 0; function step() { while (i < 1e9 && i % 1e5 !== 0) i++; if (i < 1e9) setTimeout(step); // hand control back to the event loop } step(); } ``` 2. **Використовуйте Web Workers (у браузері).** Для важких обчислень виконуйте код в окремому потоці, щоб не заважати основному. 3. **У Node.js використовуйте Worker Threads або `child_process`:** ```javascript import { Worker } from 'worker_threads'; new Worker('./heavy-task.js'); ``` 4. **Не використовуйте синхронні методи вводу-виводу:** - `fs.readFileSync`, погано; - `fs.readFile`, добре; - `crypto.pbkdf2Sync`, погано; - `crypto.pbkdf2`, добре. ### Коротко | Причина | Що відбувається | | --- | --- | | JavaScript однопотоковий | Усе виконується в одному потоці | | Блокуючий код | Затримує event loop | | UI перестає реагувати | «Фриз» інтерфейсу | | Сервер «висне» | Запити не обробляються | | Рішення | Асинхронність, чанкінг, воркери | ### Типові помилки - **Вважати, що `async`/`await` роблять код неблокуючим.** `await` лише віддає керування на час очікування; сам важкий синхронний обчислювальний блок усередині `async`-функції блокує потік так само. - **Синхронні API на сервері.** `fs.readFileSync`, `crypto.pbkdf2Sync`, `JSON.parse` на десятках мегабайтів у обробнику запиту зупиняють увесь процес, а не один запит. - **Довіряти точності `setTimeout`.** Таймер гарантує «не раніше ніж», а не «рівно через»: якщо event loop зайнятий, колбек чекатиме. - **Робити chunking через `Promise.resolve().then()`.** Це мікрозадача, вона виконається в тому самому такті й не дасть браузеру перемалювати кадр. Потрібна макрозадача: `setTimeout`, `MessageChannel` або `requestIdleCallback`. - **Передавати у Web Worker величезні об'єкти без `Transferable`.** Структурне клонування великого буфера саме по собі блокує потік; для `ArrayBuffer` використовуйте передачу володіння. - **Оптимізувати наосліп.** Спершу профайлер (вкладка Performance або `--cpu-prof` у Node.js), і лише потім переписування.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.