Skip to main content

Чому 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, а операції введення-виведення (файли, мережа, БД) делегуються фоновим потокам.

Як це працює всередині

javascript
┌───────────────────────────────────┐ │ Твій JS-код (1 потік) │ ← Event Loop └───────────────────────────────────┘ ┌──────────────────────┐ │ libuv ThreadPool │ ← 4-8 фонових потоків └──────────────────────┘ ОС: файли, мережа, DNS
  • Основний потік (event loop) виконує лише JS.
  • Якщо потрібно прочитати файл або зробити запит до бази даних - Node.js не чекає результат, а доручає задачу фоновому потоку (libuv).
  • Коли операція завершена, результат повертається назад в event loop, і викликається callback або await.

Приклад наочно

javascript
const fs = require('fs'); console.log('A'); fs.readFile('text.txt', 'utf8', () => console.log('B')); console.log('C');

Результат:

javascript
A C B

JS-код йде послідовно (A → C). Читання файлу виконується у фоні. Коли файл готовий - подія потрапляє в event loop, і виконується console.log('B').

Чому Node.js все ж не строго «однопоточний» під капотом

Node.js внутрішньо використовує кілька потоків:

  • Event loop - один потік для виконання JS.
  • Thread pool (libuv) - кілька потоків (за замовчуванням 4) для I/O операцій.
  • Системні потоки ОС - ще нижче, для мережевого стека й файлової системи.

Але! Усе це приховано від розробника - твоя логіка JS виконується лише в одному потоці, тому Node.js вважають однопоточним середовищем.

Переваги однопоточності

  1. Простота: немає гонок даних, синхронізацій, м'ютексів.
  2. Висока масштабованість: event loop + неблокуючий I/O дозволяють обслуговувати тисячі запитів одночасно.
  3. Менше ресурсів: не потрібно створювати потік під кожен запит.

Недоліки

  1. CPU-важкі операції блокують event loop. Якщо JS-код виконує довгі обчислення - сервер перестає відповідати. Рішення: worker_threads, cluster, черги задач.
  2. Одна помилка - один процес. Без обробки помилок (try/catch, process.on('uncaughtException')) можна «завалити» весь сервер.

Чи можна зробити Node.js багатопоточним?

Так, якщо потрібно задіяти всі ядра CPU, є механізми:

МеханізмМодульЩо робить
Cluster APIclusterЗапускає кілька копій процесу Node.js
Worker Threadsworker_threadsДозволяє виконувати JS-код в окремих потоках
Child Processchild_processСтворює дочірні процеси для важких задач

Підсумок

КритерійNode.js
Потік, де виконується JSОдин (Event Loop)
Потоки під капотомЄ (libuv ThreadPool)
Основна модельАсинхронна, неблокуюча
ПеревагиПростота, ефективність для I/O
НедолікиПогано підходить для важких обчислень

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

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

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