Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Типи потоків». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Чотири типи: **Readable** (лише читання, наприклад файли, `req`), **Writable** (лише запис, файли, `res`), **Duplex** (читання й запис одночасно, TCP-сокети) і **Transform** (Duplex, що ще й перетворює дані на льоту, наприклад gzip). **Ключове:** усі чотири - EventEmitter-и, і зазвичай їх з'єднують у ланцюжок через `.pipe()`, де кожен наступний потік отримує вихід попереднього.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Загальне визначення > **Потік (Stream)** - це абстракція, що дозволяє **читати чи записувати дані поступово**, > по шматках (*chunks*), не завантажуючи все в пам'ять одразу. Кожен потік - це об'єкт, який реалізує **інтерфейс EventEmitter** (він генерує події на кшталт `'data'`, `'end'`, `'error'`, `'finish'`). ## 2. Основні типи потоків у Node.js | Тип | Призначення | Приклад використання | Основні методи/події | |---|---|---|---| | **Readable** | Читання даних | Читання файлів, HTTP-запитів, stdin | `.on('data')`, `.pipe()`, `.read()` | | **Writable** | Запис даних | Запис у файл, HTTP-відповідь, stdout | `.write()`, `.end()`, `.on('finish')` | | **Duplex** | Двосторонній потік (читання + запис) | TCP-сокети, WebSocket | `.write()`, `.read()`, `.pipe()` | | **Transform** | Duplex + перетворення даних "на льоту" | Стиснення (zlib), шифрування (crypto) | `.pipe()`, `.transform()` | ## Readable Stream (потік для читання) Це джерело даних - потік, з якого **читають**. **Приклади:** - читання файлу через `fs.createReadStream()`, - тіло HTTP-запиту (`req` у `http.createServer()`), - потік введення (`process.stdin`). **Приклад:** ```javascript const fs = require('fs'); const readable = fs.createReadStream('file.txt', 'utf8'); readable.on('data', chunk => { console.log('Отримано шматок:', chunk.length); }); readable.on('end', () => { console.log('Читання завершено'); }); ``` Потік читає дані **поступово** й викликає подію `'data'` для кожного чанка. ## Writable Stream (потік для запису) Це приймач даних - потік, **у який записують**. **Приклади:** - запис у файл через `fs.createWriteStream()`, - надсилання відповіді (`res`) в HTTP-сервері, - виведення в консоль (`process.stdout`). **Приклад:** ```javascript const fs = require('fs'); const writable = fs.createWriteStream('output.txt'); writable.write('Перший рядок\n'); writable.write('Другий рядок\n'); writable.end('Файл записано'); writable.on('finish', () => { console.log('Запис завершено'); }); ``` Потік приймає дані частинами через `.write()`, і повідомляє про завершення через подію `'finish'`. ## Duplex Stream (двонаправлений потік) Це потік, який може **одночасно читати й записувати** дані. Він поєднує можливості `Readable` і `Writable`. **Приклади:** - мережеві з'єднання (`net.Socket`), - WebSocket-з'єднання, - потік TCP (один потік читає й пише). **Приклад:** ```javascript const { Duplex } = require('stream'); const duplex = new Duplex({ read(size) { this.push('дані з duplex\n'); this.push(null); }, write(chunk, encoding, callback) { console.log('Записано:', chunk.toString()); callback(); } }); duplex.on('data', chunk => console.log('Читання:', chunk.toString())); duplex.write('Hello Duplex!'); ``` Duplex корисний для **двостороннього обміну** (наприклад, сокети, тунелі, протоколи). ## Transform Stream (трансформаційний потік) Це **особливий вид Duplex-потоку**, який **перетворює** дані "на льоту" під час проходження. **Приклади:** - стиснення (`zlib.createGzip()`), - шифрування (`crypto.createCipher()`), - перетворення тексту (наприклад, у верхній регістр). **Приклад:** ```javascript const { Transform } = require('stream'); const upperCase = new Transform({ transform(chunk, encoding, callback) { this.push(chunk.toString().toUpperCase()); callback(); } }); process.stdin.pipe(upperCase).pipe(process.stdout); ``` Усе, що ти введеш у консоль, виведеться у верхньому регістрі. ## 3. Взаємодія потоків Зазвичай потоки з'єднують за допомогою `.pipe()`: ```javascript const fs = require('fs'); const zlib = require('zlib'); fs.createReadStream('file.txt') .pipe(zlib.createGzip()) // Transform stream (стиснення) .pipe(fs.createWriteStream('file.txt.gz')); // Writable stream ``` Тут: - `createReadStream` → джерело даних (Readable) - `createGzip` → перетворення (Transform) - `createWriteStream` → приймач (Writable) Потоки з'єднуються як конвеєр (*pipeline*), передаючи дані частинами без блокування пам'яті. ## 4. Події та методи потоків | Тип потоку | Ключові події | Основні методи | |---|---|---| | **Readable** | `'data'`, `'end'`, `'error'` | `.read()`, `.pipe()`, `.pause()`, `.resume()` | | **Writable** | `'drain'`, `'finish'`, `'error'` | `.write()`, `.end()` | | **Duplex** | поєднує обидва набори | `.read()`, `.write()` | | **Transform** | `'data'`, `'finish'`, `'error'` | `.pipe()`, `.transform()` | ## 5. Де використовуються ці типи потоків | Модуль | Використовує потоки | |---|---| | `fs` | читання/запис файлів (`createReadStream`, `createWriteStream`) | | `http` | `req` і `res` - потоки (Readable/Writable) | | `zlib` | стиснення / розпакування (Transform) | | `crypto` | шифрування / хешування (Transform) | | `net` | TCP-з'єднання (Duplex) | | `process` | `stdin`, `stdout`, `stderr` - потоки | ## Підсумок | Тип | Призначення | Приклад | |---|---|---| | **Readable** | Джерело даних (читання) | `fs.createReadStream()`, `req` | | **Writable** | Приймач даних (запис) | `fs.createWriteStream()`, `res` | | **Duplex** | Читання + запис одночасно | `net.Socket`, WebSocket | | **Transform** | Читання + запис + перетворення | `zlib.createGzip()`, `crypto.createCipher()` | **Висновок:** > У Node.js існує **чотири типи потоків** - > **Readable**, **Writable**, **Duplex** і **Transform**. > > Вони дозволяють: > > - читати, записувати й перетворювати дані **поступово**, > - працювати з великими файлами й мережевими потоками **ефективно**, > - і будувати **ланцюжки обробки даних** без завантаження всієї інформації в пам'ять.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.