pipe()
Тема дорожной карты · Node.js
Метод pipe() — это фундаментальный API потоков Node.js, соединяющий поток Readable с потоком Writable и автоматически управляющий потоком данных и backpressure, чтобы источник не перегружал потребителя. При вызове readable.pipe(writable) среда выполнения Node.js передаёт фрагменты данных с читаемой стороны на записываемую и приостанавливает читаемый поток, когда внутренний буфер записываемого потока заполнен, предотвращая исчерпание памяти в серверных приложениях Node.js, обрабатывающих большие файлы или сетевые ответы. pipe() поддерживает цепочку через потоки Transform — например, fs.createReadStream('input.gz').pipe(zlib.createGunzip()).pipe(fs.createWriteStream('output.txt')) эффективно распаковывает gzip-файл без буферизации всего содержимого в памяти. Современная альтернатива stream.pipeline() из модуля stream предпочтительнее pipe() в продакшн-коде Node.js, поскольку правильно распространяет ошибки и вызывает колбэки очистки при завершении или сбое конвейера, тогда как pipe() при ошибке может оставить незакрытые дескрипторы. Оба метода — pipe() и pipeline() — являются критически важными примитивами производительности для обработки файлов, HTTP-проксирования и преобразования данных в серверной разработке Node.js.
Как это работает
pipe() в Node — это unix-pipe-подобные абстракции для инкрементальных данных: Readable, Writable, Duplex, Transform. Используйте, когда данные большие (GB-файлы, сетевые загрузки) или бесконечные (логи, websockets). Современный Node поддерживает stream/promises и pipeline() для безопасной композиции с обработкой ошибок и cleanup. Web Streams API (ReadableStream, WritableStream) доступен с Node 18 — тот же shape, что в браузере.
Когда применять
Streams — когда payload может превысить RAM: загрузки файлов, большие выборки из БД, CSV-импорт. pipeline() (не сырой .pipe()) — чтобы ошибки пробрасывались, ресурсы закрывались. Для HTTP-ответов можно return res.pipe(stream) — forward без буферизации. Пропустите streams для маленьких in-memory данных — overhead API больше выгоды; берите buffer или string.
Типичные ошибки
Ловушки pipe(): забытый backpressure (медленный consumer, быстрый producer = раздутая память); .pipe() без error-обработчиков (тихий провал); смешение object-mode и binary-mode streams; конверсия stream → Buffer ради JSON.parse (теряет смысл). for await (const chunk of stream) в современном Node — читается чище, чем event-обработчики.