Потоки (streams) та I/O операції
Що таке потік (stream) у Node.js
Потік (stream) - це послідовне джерело чи отримувач даних, який дозволяє обробляти дані частинами (chunk), не чекаючи завантаження всього вмісту цілком.
Іншими словами:
Потоки - це спосіб читати чи записувати дані поступово, а не цілком.
Приклади потоків у Node.js:
| Тип потоку | Приклад використання | Модуль |
|---|---|---|
| Readable (для читання) | Читання файлу, отримання даних з HTTP-запиту | fs.createReadStream(), http.IncomingMessage |
| Writable (для запису) | Запис у файл, надсилання HTTP-відповіді | fs.createWriteStream(), http.ServerResponse |
| Duplex (двонаправлений) | TCP-сокет (можна читати й писати) | net.Socket |
| Transform (трансформаційний) | Стиснення, шифрування, обробка даних на льоту | zlib.createGzip(), crypto.createCipher() |
Приклад: читання файлу за допомогою потоку
const fs = require('fs');
const readStream = fs.createReadStream('bigfile.txt', 'utf8');
readStream.on('data', chunk => {
console.log('Отримано частину даних:', chunk.length);
});
readStream.on('end', () => {
console.log('Файл прочитано повністю.');
});Тут Node.js не завантажує весь файл у пам'ять, а читає його порціями (chunks) і обробляє в міру надходження.
Чому потоки - основний спосіб роботи з I/O
1. Економія пам'яті
Якщо ти читаєш файл на 10 ГБ через fs.readFile(),
Node.js спробує завантажити весь файл в оперативну пам'ять - і впаде через OOM (Out Of Memory).
Потоки ж читають по шматках, зберігаючи постійне використання пам'яті.
2. Висока продуктивність
Дані можна обробляти одразу під час надходження, не чекаючи, поки весь файл, запит чи відповідь будуть готові.
Наприклад:
- потік даних із камери можна транскодувати "на льоту";
- HTTP-запит можна одразу почати віддавати клієнту без буферизації всієї відповіді.
3. Асинхронність і backpressure
Потоки вбудовані в архітектуру EventEmitter, працюють асинхронно і підтримують backpressure - механізм, що запобігає "заливанню" приймача даними швидше, ніж він може їх обробити.
Наприклад:
readable.pipe(writable);Якщо writable тимчасово не встигає записувати, Node.js автоматично призупиняє читання, поки writable не звільниться.
4. Складеність
Потоки можна з'єднувати (pipe) між собою як конвеєр:
const fs = require('fs');
const zlib = require('zlib');
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));Тут дані:
- читаються з файлу,
- стискаються,
- і записуються назад - усе без проміжних тимчасових файлів і без завантаження в пам'ять.
Усередині Node.js
Потоки базуються на модулі stream
і лежать в основі більшості вбудованих API:
http(запити й відповіді),fs(робота з файлами),net(TCP),zlib,crypto(стиснення, шифрування),process.stdin,process.stdout.
Підсумок
Потоки (Streams) у Node.js - це інтерфейс для роботи з даними частинами, який:
- дозволяє читати, писати й обробляти дані поступово;
- заощаджує пам'ять і прискорює I/O;
- підтримує асинхронну роботу й backpressure;
- є універсальним механізмом для всього I/O в Node.js (файли, мережа, HTTP, процеси, шифрування тощо).
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.