Що таке streams у Node.js?
Node.js Потоки
Потоки є однією з найпотужніших функцій Node.js. Вони дозволяють вам обробляти дані частинами (по шматочках), а не завантажувати все в пам'ять одночасно — це необхідно для роботи з великими файлами, мережевими даними або обробкою в реальному часі.
Чому Потоки?
js
// БЕЗ потоків — завантажує весь файл в пам'ять ❌
const data = fs.readFileSync('huge-file.mp4'); // 4 ГБ в ОП!
res.end(data);
// З ПОТОКАМИ — обробляє частинами ✅
fs.createReadStream('huge-file.mp4').pipe(res);Чотири Типи Потоків
| Тип | Опис | Приклад |
|---|---|---|
| Readable | Джерело даних | fs.createReadStream(), http.IncomingMessage |
| Writable | Призначення для даних | fs.createWriteStream(), http.ServerResponse |
| Duplex | І читабельний, і записуваний | net.Socket, zlib.createGzip() |
| Transform | Дуплекс, що модифікує дані | crypto.createCipher(), zlib |
Читабельний Потік
js
const fs = require('fs');
const readable = fs.createReadStream('./large-file.txt', {
encoding: 'utf8',
highWaterMark: 64 * 1024 // 64КБ шматки
});
readable.on('data', chunk => {
console.log(`Отримано ${chunk.length} байт`);
});
readable.on('end', () => console.log('Читання завершено'));
readable.on('error', err => console.error(err));Записувальний Потік
js
const fs = require('fs');
const writable = fs.createWriteStream('./output.txt');
writable.write('Привіт, ');
writable.write('Потоки!');
writable.end('
');
writable.on('finish', () => console.log('Запис завершено'));pipe() — З'єднання Потоків
pipe() автоматично обробляє зворотний тиск і з'єднує читабельний з записувальним:
js
const fs = require('fs');
const zlib = require('zlib');
// Читати → Стиснути → Записати (все в потоковому режимі, низька пам'ять)
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));pipeline() — Сучасний підхід (Node.js 10+)
js
const { pipeline } = require('stream/promises');
const fs = require('fs');
const zlib = require('zlib');
await pipeline(
fs.createReadStream('input.txt'),
zlib.createGzip(),
fs.createWriteStream('input.txt.gz')
);
// Автоматично обробляє помилки та очищенняПотік Перетворення (Користувацький)
js
const { Transform } = require('stream');
const upperCaseTransform = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
});
process.stdin.pipe(upperCaseTransform).pipe(process.stdout);Зворотний Тиск
Коли споживач повільніший за виробника, Node.js автоматично призупиняє читання:
js
const readable = fs.createReadStream('./huge.bin');
const writable = fs.createWriteStream('./copy.bin');
readable.on('data', chunk => {
const canContinue = writable.write(chunk);
if (!canContinue) {
readable.pause(); // зупинити читання, поки записувальний не спустошиться
writable.once('drain', () => readable.resume());
}
});pipe() автоматично обробляє зворотний тиск.
Резюме
Використовуйте потоки, коли:
- Обробляєте великі файли (відео, журнали, CSV)
- Працюєте з HTTP запитами/відповідями
- Створюєте потоки даних в реальному часі
- Зменшуєте використання пам'яті вашого додатку
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.