Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як з'єднати кілька потоків підряд?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Класичний спосіб - `.pipe()`, який повертає наступний потік, тож виклики можна з'єднувати ланцюжком (`readable.pipe(transform).pipe(writable)`); сучасний і безпечніший - `stream.pipeline()`, який автоматично обробляє помилки й підтримує `await` через `stream/promises`. **Ключове:** якщо використовуєш `.pipe()` без `pipeline()`, обов'язково підписуйся на `stream.on('error', ...)` на кожному потоці - інакше необроблена помилка завершить процес.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Способи з'єднання потоків Є **два основні способи**: 1. **Класичний - через** `.pipe()` 2. **Сучасний і безпечний - через** `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, - форматувати текст, - логувати дані тощо. ## Ключові правила при з'єднанні потоків 1. **Порядок важливий** - дані течуть зліва направо. 2. **Кожен** `.pipe()` **повертає наступний потік**, що дозволяє будувати ланцюжки. 3. **Не забувай про помилки**, якщо використовуєш `.pipe()` без `pipeline()`: ```javascript stream.on('error', console.error); ``` 4. **Використовуй** `pipeline()` **для продакшену** - він сам закриє все в разі збою.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.