Що означає термін non-blocking
Термін «non-blocking» (неблокуючий) означає, що виконання програми не зупиняється, поки очікується завершення довгої операції, наприклад мережевого запиту, таймера або читання файлу. Простіше кажучи, non-blocking, це «не чекай, продовжуй виконувати інший код».
Теорія
TL;DR
- Неблокуючий код не призупиняє основний потік виконання.
- Поки асинхронна операція працює «у фоні», JS виконує інші задачі.
- Реалізовано це через однопотокову модель, Event Loop, асинхронні API і черги задач.
setTimeout,fetch,fs.readFile, це неблокуючі операції.- Важкий синхронний цикл, навпаки, блокує все, включно з інтерфейсом.
- Node.js побудований навколо non-blocking I/O, тому один процес обслуговує багато запитів.
Швидкий приклад
console.log('A');
setTimeout(() => {
console.log('B');
}, 2000);
console.log('C');Вивід:
A
C
BsetTimeout, це non-blocking операція: вона не зупиняє виконання програми, а планує виклик колбека пізніше.
Блокуючий і неблокуючий код
Блокуючий варіант:
function sleep(ms) {
const start = Date.now();
while (Date.now() - start < ms) {} // блокує потік
}
console.log('A');
sleep(2000);
console.log('B');Вивід (через 2 секунди):
A
BУсе «зависло» на 2 секунди: доки працює sleep(), ні інтерфейс, ні інші скрипти не виконуються. Це blocking код.
Неблокуючий варіант із setTimeout (див. швидкий приклад вище) дає A, C, B: рядок C виконується одразу, а B чекає своєї черги, не займаючи потік.
Як це працює під капотом
Неблокуюча поведінка досягається за рахунок:
- однопотокової моделі JS, де все проходить через Event Loop;
- асинхронних API (браузерних або Node.js);
- черг задач (Callback Queue), де чекають готові результати.
JS відправляє операцію (наприклад, fetch) у зовнішній API і не чекає, а виконує код далі. Коли результат готовий, колбек повертається в чергу, і Event Loop виконає його, щойно стек викликів звільниться.
Non-blocking у Node.js
Node.js побудований навколо non-blocking I/O (вводу та виводу). Це означає:
- операції з файлами, мережею, базою даних є асинхронними;
- замість очікування результату Node продовжує обслуговувати інші запити.
const fs = require('fs');
console.log('Start');
fs.readFile('file.txt', 'utf8', (err, data) => {
console.log('File has been read');
});
console.log('End');Вивід:
Start
End
File has been readЧитання файлу тут non-blocking: Node не чекає його завершення, а виконує решту коду.
Чому це важливо
| Підхід | Що робить | Недолік |
|---|---|---|
| Blocking | Виконує операції строго послідовно | «Підвішує» потік, гальмує інтерфейс |
| Non-blocking | Дозволяє виконувати інші задачі під час очікування | Треба вміти працювати з колбеками та промісами |
Асинхронність і неблокуюча поведінка роблять JS чуйним та ефективним, особливо в браузері й у серверних застосунках.
Життєва аналогія: уявіть офіціанта в кафе.
- Блокуючий підхід: він стоїть і чекає, поки приготують замовлення клієнта, і лише потім приймає наступне.
- Неблокуючий підхід: він передає замовлення на кухню і обслуговує інших клієнтів, поки страва готується.
JavaScript поводиться як другий офіціант.
Підсумок термінів
| Термін | Значення |
|---|---|
| Blocking | Виконання зупиняється, доки операція не завершиться |
| Non-blocking | Виконання продовжується, а результат обробляється пізніше |
| Реалізація | Через Event Loop, асинхронні колбеки, проміси |
| Перевага | Не «заморожує» потік, швидкий відгук |
Типові помилки
- Вважати, що non-blocking означає багатопотоковість: код усе одно виконується в одному потоці.
- Писати власний
sleep()на цикліwhileзамістьawait new Promise(r => setTimeout(r, ms)). - Використовувати синхронні варіанти API Node.js (
fs.readFileSync) у коді, що обслуговує запити. - Робити важкі обчислення в основному потоці: навіть асинхронний код не врятує від блокування.
- Думати, що
awaitблокує потік: він призупиняє лише своюasync-функцію, а потік залишається вільним.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.