Skip to main content

Чому Node.js реалізує «non-blocking I/O»?

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

Node.js реалізує non-blocking I/O (неблокуюче введення/виведення), щоб не блокувати головний потік виконання під час очікування "повільних" операцій (читання файлів, мережеві запити, робота з БД тощо), і обслуговувати тисячі одночасних з'єднань в одному процесі.

1. Контекст: однопоточність Node.js

Node.js працює в одному основному потоці - тобто:

  • у нього немає окремого потоку на кожен запит (як у Java, PHP, Python);
  • увесь код виконується послідовно всередині Event Loop.

Тому, якщо одна операція заблокує потік (наприклад, fs.readFileSync() на 200 МБ файл), увесь сервер "зависне", і інші запити не зможуть оброблятися.

2. Що робить non-blocking I/O

Замість того щоб чекати завершення I/O, Node.js:

  1. надсилає задачу в систему (диск, мережу, БД),
  2. одразу повертає керування,
  3. реєструє callback/Promise, який буде викликано, коли дані готові.

Таким чином:

  • потік вільний для виконання інших задач;
  • десятки тисяч операцій введення-виведення можуть виконуватися паралельно (у фоні, через ОС і libuv).

3. Технічна реалізація

Node.js використовує бібліотеку libuv, яка:

  • керує Event Loop,
  • реалізує асинхронні операції I/O через epoll / kqueue / IOCP (залежно від ОС),
  • використовує Thread Pool (для деяких операцій, наприклад fs).

Коли I/O завершується - результат потрапляє в чергу подій, і Event Loop викликає твій callback / then / await.

4. Приклад: синхронний vs асинхронний I/O

javascript
// Блокуючий варіант const data = fs.readFileSync('file.txt', 'utf8'); console.log(data); console.log('Цей лог виконається лише після читання файлу'); // Неблокуючий варіант fs.readFile('file.txt', 'utf8', (err, data) => { console.log(data); }); console.log('Цей лог виконається одразу, не чекаючи файлу');

5. Навіщо це потрібно

МетаПояснення
Висока продуктивністьОдин потік може обслуговувати тисячі клієнтів одночасно.
Менше ресурсівНе потрібно створювати новий потік на кожен запит.
Менше перемикань контекстуПотік не простоює, не витрачає ресурси на очікування.
Ефективна робота з I/ONode.js ідеально підходить для серверів, API, real-time застосунків.

6. Коли це неефективно

Якщо застосунок виконує CPU-інтенсивні обчислення (шифрування, парсинг відео, складна математика) - non-blocking I/O не допомагає, тому що обчислення займають потік, а не I/O. У таких випадках використовують:

  • Worker Threads,
  • Cluster Mode,
  • чи виносять обчислення в окремі сервіси.

Підсумок

Node.js реалізує non-blocking I/O, щоб не блокувати Event Loop під час виконання повільних операцій і тим самим обробляти безліч запитів паралельно в одному потоці. Це робить Node.js неймовірно ефективним для мережевих і I/O-навантажених застосунків - серверів, API, WebSocket-чатів і real-time систем.

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

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

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