Чому Node.js називають однопоточним середовищем?
Що взагалі означає «однопоточне середовище»
Однопоточність (single-threaded) означає, що все виконання JavaScript-коду в Node.js відбувається в одному основному потоці.
Цей потік:
- виконує твій JS-код,
- обробляє події, callback-и, проміси й async-функції,
- керується механізмом під назвою event loop (цикл подій).
Тобто в кожен момент часу Node.js виконує лише один шматок JS-коду, а не декілька одночасно.
Чому так влаштовано
Node.js базується на рушії V8 (тому самому, що й у Google Chrome), а JavaScript - спочатку однопоточна мова (створювалася для браузера, де все йде в одному потоці, щоб уникнути конфліктів під час роботи з DOM).
Творець Node.js - Раян Дал - використав цю особливість JS, але додав до нього асинхронну неблокуючу модель введення-виведення (non-blocking I/O) через бібліотеку libuv.
Результат:
Один потік виконує JavaScript, а операції введення-виведення (файли, мережа, БД) делегуються фоновим потокам.
Як це працює всередині
┌───────────────────────────────────┐
│ Твій JS-код (1 потік) │ ← Event Loop
└───────────────────────────────────┘
↓
┌──────────────────────┐
│ libuv ThreadPool │ ← 4-8 фонових потоків
└──────────────────────┘
↓
ОС: файли, мережа, DNS- Основний потік (event loop) виконує лише JS.
- Якщо потрібно прочитати файл або зробити запит до бази даних -
Node.js не чекає результат, а доручає задачу фоновому потоку (
libuv). - Коли операція завершена, результат повертається назад в event loop, і викликається callback або
await.
Приклад наочно
const fs = require('fs');
console.log('A');
fs.readFile('text.txt', 'utf8', () => console.log('B'));
console.log('C');Результат:
A
C
BJS-код йде послідовно (A → C).
Читання файлу виконується у фоні.
Коли файл готовий - подія потрапляє в event loop, і виконується console.log('B').
Чому Node.js все ж не строго «однопоточний» під капотом
Node.js внутрішньо використовує кілька потоків:
- Event loop - один потік для виконання JS.
- Thread pool (libuv) - кілька потоків (за замовчуванням 4) для I/O операцій.
- Системні потоки ОС - ще нижче, для мережевого стека й файлової системи.
Але! Усе це приховано від розробника - твоя логіка JS виконується лише в одному потоці, тому Node.js вважають однопоточним середовищем.
Переваги однопоточності
- Простота: немає гонок даних, синхронізацій, м'ютексів.
- Висока масштабованість: event loop + неблокуючий I/O дозволяють обслуговувати тисячі запитів одночасно.
- Менше ресурсів: не потрібно створювати потік під кожен запит.
Недоліки
- CPU-важкі операції блокують event loop.
Якщо JS-код виконує довгі обчислення - сервер перестає відповідати.
Рішення:
worker_threads,cluster, черги задач. - Одна помилка - один процес.
Без обробки помилок (
try/catch,process.on('uncaughtException')) можна «завалити» весь сервер.
Чи можна зробити Node.js багатопоточним?
Так, якщо потрібно задіяти всі ядра CPU, є механізми:
| Механізм | Модуль | Що робить |
|---|---|---|
| Cluster API | cluster | Запускає кілька копій процесу Node.js |
| Worker Threads | worker_threads | Дозволяє виконувати JS-код в окремих потоках |
| Child Process | child_process | Створює дочірні процеси для важких задач |
Підсумок
| Критерій | Node.js |
|---|---|
| Потік, де виконується JS | Один (Event Loop) |
| Потоки під капотом | Є (libuv ThreadPool) |
| Основна модель | Асинхронна, неблокуюча |
| Переваги | Простота, ефективність для I/O |
| Недоліки | Погано підходить для важких обчислень |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.