Чому 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:
- надсилає задачу в систему (диск, мережу, БД),
- одразу повертає керування,
- реєструє 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
// Блокуючий варіант
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/O | Node.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 систем.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.