Як з'єднати кілька потоків підряд?
Способи з'єднання потоків
Є два основні способи:
- Класичний - через
.pipe() - Сучасний і безпечний - через
stream.pipeline()
1. З'єднання через .pipe()
Метод .pipe() - це найбазовіший спосіб "зв'язувати" потоки.
Він передає вивід одного потоку (Readable) на вхід іншого (Writable чи Transform):
javascript
const fs = require('fs');
const zlib = require('zlib');
fs.createReadStream('input.txt') // Readable
.pipe(zlib.createGzip()) // Transform
.pipe(fs.createWriteStream('output.txt.gz')); // WritableЩо відбувається:
createReadStream()читає файл частинами (chunks),createGzip()стискає їх "на льоту",createWriteStream()записує в новий файл.
Ланцюжок із кількох Transform-потоків
javascript
const fs = require('fs');
const { Transform } = require('stream');
const zlib = require('zlib');
// 1. Перетворюємо текст у верхній регістр
const upper = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
},
});
// 2. Стискаємо результат
const gzip = zlib.createGzip();
fs.createReadStream('input.txt')
.pipe(upper) // Readable → Transform
.pipe(gzip) // Transform → Transform
.pipe(fs.createWriteStream('output.txt.gz')); // Transform → WritableКожен
.pipe()повертає наступний потік, тож можна вибудовувати довгі ланцюжки.
2. З'єднання через pipeline()
Починаючи з Node.js v10, з'явився метод pipeline() (у stream),
який робить те саме, але безпечніше й надійніше.
javascript
const { pipeline } = require('stream');
const fs = require('fs');
const zlib = require('zlib');
pipeline(
fs.createReadStream('input.txt'),
zlib.createGzip(),
fs.createWriteStream('output.txt.gz'),
(err) => {
if (err) console.error('Помилка в потоці:', err);
else console.log('Файл успішно оброблено!');
}
);Переваги pipeline() перед .pipe()
| Особливість | .pipe() | pipeline() |
|---|---|---|
| Обробка помилок | Потрібно вручну | Автоматично |
| Завершення всіх потоків при помилці | Немає | Є |
| Callback / Promise по завершенню | Немає | Є |
Підтримка async/await (stream/promises) | Немає | Є |
3. Асинхронний варіант (stream/promises)
Сучасний спосіб із await (Node.js 15+):
javascript
import { pipeline } from 'stream/promises';
import fs from 'fs';
import zlib from 'zlib';
import { Transform } from 'stream';
const upper = new Transform({
transform(chunk, _, cb) {
cb(null, chunk.toString().toUpperCase());
},
});
await pipeline(
fs.createReadStream('input.txt'),
upper,
zlib.createGzip(),
fs.createWriteStream('output.txt.gz')
);
console.log('Усі потоки успішно завершено');Узагальнена схема ланцюжка потоків
javascript
Readable → Transform → Transform → Writable
↓ ↓ ↓ ↓
Джерело Фільтр 1 Фільтр 2 ПриймачКожен Transform може:
- стискати,
- шифрувати,
- фільтрувати,
- парсити JSON,
- форматувати текст,
- логувати дані тощо.
Ключові правила при з'єднанні потоків
- Порядок важливий - дані течуть зліва направо.
- Кожен
.pipe()повертає наступний потік, що дозволяє будувати ланцюжки. - Не забувай про помилки, якщо використовуєш
.pipe()безpipeline():
javascript
stream.on('error', console.error);- Використовуй
pipeline()для продакшену - він сам закриє все в разі збою.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.