Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Неблокуючий код». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Неблокуючий код не зупиняє основний потік, а делегує довгі операції (I/O, мережа, таймери, файли) середовищу виконання і продовжує роботу над іншими задачами.** Блокуючий код, навпаки, тримає main thread до свого завершення: поки він працює, JavaScript не обробляє кліки, не перемальовує інтерфейс і не запускає наступні функції. Це критично, бо JS однопотоковий, тому асинхронні API, Web API, libuv та event loop повертають результат тоді, коли він готовий. ```javascript console.log('start'); setTimeout(() => console.log('one second passed'), 1000); console.log('end'); // start, end, one second passed ``` **Ключове:** неблокуючий не означає паралельний, рушій усе одно виконує один колбек за раз, просто не марнує час на очікування.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Неблокуючий код, це код, який не зупиняє виконання потоку, а делегує довгі операції (I/O, мережа, таймери, файли) і продовжує виконувати інші задачі.** Його протилежність, блокуючий код, не відпускає основний потік (main thread), доки не завершиться. ## Теорія ### TL;DR - Блокуючий код тримає main thread: поки він працює, немає ні обробки кліків, ні перемальовування інтерфейсу, ні наступних функцій. - Неблокуючий код віддає довгу операцію назовні і одразу йде далі, а результат отримує пізніше через колбек чи промайс. - Це важливо, бо JavaScript однопотоковий: якщо один шматок коду «завис», решта чекає. - Механіка: асинхронні API (`setTimeout`, `fetch`, `async/await`), зовнішні Web API або пул потоків libuv, плюс event loop, який повертає результат. - Типові неблокуючі операції: таймери, мережа, файли в Node.js, запити до БД, обробники подій, промайси. - Неблокуючий не дорівнює паралельний: рушій виконує один колбек за раз, просто не простоює під час очікування. ### Швидкий приклад ```javascript console.log('start'); setTimeout(() => { console.log('one second passed'); }, 1000); console.log('end'); // start // end // one second passed ``` Потік не був заблокований: JS вільно обробляв інші події, поки таймер «працював у фоні». ### Що таке блокуючий код Блокуючий код не відпускає основний потік, поки не завершиться. Поки операція виконується, JavaScript **не може робити нічого іншого**. ```javascript // Імітація довгого розрахунку function heavyCalculation() { const start = Date.now(); while (Date.now() - start < 3000) {} // чекаємо 3 секунди console.log('calculation finished'); } console.log('start'); heavyCalculation(); console.log('end'); ``` Результат: ```javascript start (зависає на 3 секунди) calculation finished end ``` Усе стало на 3 секунди: інтерфейс «замерз», сервер не відповідає. Це і є blocking code. ### Що таке неблокуючий код Неблокуючий варіант тієї самої затримки: ```javascript console.log('start'); setTimeout(() => { console.log('one second passed'); }, 1000); console.log('end'); ``` Що відбувається: 1. JS викликає `setTimeout` і передає задачу браузеру (Web API). 2. Виконання продовжується, `'end'` друкується одразу. 3. Через 1 секунду колбек повертається у **чергу задач** і виконується. Результат: ```javascript start end one second passed ``` ### Чому це важливо в JavaScript JavaScript **однопотоковий**, тобто: - у кожен момент часу виконується **лише один шматок коду**; - якщо один шматок «завис», решта чекає. Щоб уникнути «зависань», JS використовує: - **асинхронність** (`setTimeout`, `fetch`, `async/await`); - **зовнішні API** (Web APIs або пул потоків libuv); - **event loop**, щоб повернути результат, коли він готовий. Приклади неблокуючих операцій: | Тип операції | Приклад | Що робить | | --- | --- | --- | | Таймери | `setTimeout`, `setInterval` | виконуються пізніше | | Мережа | `fetch`, `XMLHttpRequest` | чекають на відповідь сервера у фоні | | Файли (Node.js) | `fs.readFile` | читають диск асинхронно | | Запити до БД | `db.query` | чекають на результат без блокування | | Обробники подій | `addEventListener('click')` | спрацьовують за подією | | Промайси | `Promise`, `async/await` | відкладають виконання до завершення операції | ### Різниця на прикладі Node.js Блокуючий варіант: ```javascript const fs = require('fs'); console.log('reading the file...'); const data = fs.readFileSync('large.txt', 'utf8'); // блокує потік console.log('file read:', data.length); ``` Поки файл читається, **сервер не обслуговує інші запити**. Неблокуючий варіант: ```javascript const fs = require('fs'); console.log('reading the file...'); fs.readFile('large.txt', 'utf8', (err, data) => { console.log('file read:', data.length); }); console.log('other code keeps running...'); ``` Node.js віддає задачу системі (I/O) і продовжує виконання. Коли файл готовий, колбек повертається через **event loop**. ### Чому «неблокуючий» не дорівнює «паралельний» Це часта помилка на співбесідах. Неблокуючий код не означає, що все працює паралельно. JS так само **виконує один колбек за раз**, але **не витрачає час даремно**, очікуючи на I/O. У цей час рушій обробляє інші задачі, тому й виникає враження паралельності. | Тип | Що робить | Приклад | Наслідок | | --- | --- | --- | --- | | **Блокуючий** | Зупиняє потік, доки не завершиться | `fs.readFileSync()` | Зависає UI або сервер | | **Неблокуючий** | Делегує задачу, продовжує роботу | `fs.readFile()`, `fetch()` | Висока чутливість інтерфейсу | Підсумок: неблокуючий код, це спосіб писати програми, де довгі операції (I/O, мережа, таймери) виконуються **асинхронно**, не заважаючи основній логіці і не «заморожуючи» потік. Він лежить в основі асинхронності JS (колбеки, промайси, `async/await`), продуктивності Node.js і плавності інтерфейсів у браузері. ### Типові помилки - Вважати `async` функцію автоматично неблокуючою. Важкий цикл усередині `async` функції блокує потік так само, як звичайний. - Використовувати синхронні варіанти API на сервері: `fs.readFileSync`, `crypto.pbkdf2Sync`, `zlib.gzipSync` зупиняють обробку всіх запитів. - Плутати неблокуючість із паралельністю і чекати, що два `await` підряд виконаються одночасно. Для справжньої одночасності потрібен `Promise.all`. - Думати, що затримка в `setTimeout` точна. Це мінімальна затримка: колбек чекатиме, поки стек не спорожніє. - Забувати про CPU-bound роботу: винести її з потоку можуть лише Web Workers, Worker Threads або нативний код, а не асинхронний синтаксис.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.