Skip to main content

Що таке Transform stream?

Transform Stream - це особливий вид потоку в Node.js, що одночасно є Readable і Writable, але на відміну від звичайного Duplex, він перетворює дані, що проходять через нього.

Простіше кажучи: Transform Stream = Duplex Stream + перетворення даних.

Концепція

Transform Stream приймає вхідні дані → обробляє їх → видає змінений результат. Він використовується, коли потрібно обробляти потік даних "на льоту", не чекаючи його завершення.

Приклади вбудованих Transform Streams

МодульПрикладОпис
zlibzlib.createGzip() / zlib.createGunzip()Стиснення й розпакування даних
cryptocrypto.createCipheriv() / createDecipheriv()Шифрування / дешифрування
streamnew stream.Transform()Створення власного трансформаційного потоку
readlineЛогічні перетворення тексту порядково

Проста аналогія

Уяви конвеєр:

  • на вхід подається потік рядків,
  • потік перетворює їх (наприклад, робить toUpperCase()),
  • і видає на вихід змінені дані.

Приклад кастомного Transform Stream

javascript
const { Transform } = require('stream'); class UpperCaseTransform extends Transform { constructor(options) { super(options); } _transform(chunk, encoding, callback) { const transformed = chunk.toString().toUpperCase(); this.push(transformed); // передаємо результат далі callback(); // сигнал, що обробку завершено } } const upperCase = new UpperCaseTransform(); process.stdin.pipe(upperCase).pipe(process.stdout);

Тут:

  • process.stdin - потік введення (Readable),
  • upperCase - наш Transform-потік (змінює дані),
  • process.stdout - потік виведення (Writable).

Усе, що ти введеш у консоль, виведеться великими літерами.

Основні методи Transform Stream

МетодОпис
_transform(chunk, encoding, callback)Головний метод - перетворює вхідні дані
_flush(callback)Викликається, коли вхідний потік завершено - можна "допушити" залишки даних
.push(data)Передає оброблені дані у вихідний потік

Приклад із _flush()

javascript
class JSONLinesTransform extends Transform { constructor() { super({ readableObjectMode: true }); this.buffer = ''; } _transform(chunk, encoding, callback) { this.buffer += chunk.toString(); let lines = this.buffer.split('\n'); this.buffer = lines.pop(); // лишаємо останній неповний рядок for (const line of lines) { if (line.trim()) { this.push(JSON.parse(line)); } } callback(); } _flush(callback) { if (this.buffer.trim()) { this.push(JSON.parse(this.buffer)); } callback(); } }

Цей потік:

  • читає рядки JSON порядково,
  • перетворює їх на об'єкти JavaScript,
  • і передає далі як stream об'єктів.

Типові сценарії використання Transform Streams

ЗадачаПриклад
Стиснення файлівfs.createReadStream('file.txt').pipe(zlib.createGzip()).pipe(fs.createWriteStream('file.gz'))
Шифруванняfs.createReadStream('data').pipe(crypto.createCipheriv(...)).pipe(fs.createWriteStream('data.enc'))
Форматування данихJSON → CSV, XML → JSON тощо
Логування / фільтрація / дебаунсПотокове перетворення логів, HTTP-запитів, даних сенсорів

Різниця між Duplex і Transform

ВластивістьDuplexTransform
Читання й записТакТак
Перетворює даніНіТак
Вхід і вихід пов'язаніНіТак
ПрикладTCP-сокетgzip, cipher, JSON-парсер

Переваги Transform Stream

  • Асинхронна обробка потоку "на льоту"
  • Економія пам'яті - не потрібно тримати весь файл у RAM
  • Проста композиція (pipe()-ланцюжки)
  • Легко розширюється - можна писати власні перетворювачі

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.