Readable и Writable
Тема дорожной карты · Node.js
Readable и Writable — это два базовых абстрактных потока в API потоков Node.js, представляющих источник данных, который можно потреблять, и назначение, которое может принимать данные, соответственно. Поток Readable в Node.js работает либо в режиме потока (flowing mode, события данных генерируются автоматически), либо в режиме паузы (paused mode, данные запрашиваются явно через read()); распространённые встроенные реализации Readable включают fs.createReadStream(), http.IncomingMessage и process.stdin. Поток Writable принимает данные через метод write(chunk) и сигнализирует о завершении через end(), а встроенные примеры включают fs.createWriteStream(), http.ServerResponse и process.stdout. Потоки Node.js реализуют backpressure через возвращаемое значение writable.write() — когда метод возвращает false, источник Readable должен приостановиться до срабатывания события drain, предотвращая исчерпание памяти, когда быстрый источник питает медленного потребителя. Оба — Readable и Writable — наследуют от EventEmitter и поддерживают события 'error', 'close' и 'finish', которые являются критически важными хуками жизненного цикла для построения надёжного файлового I/O и сетевой обработки в серверной разработке Node.js.
Как это работает
Readable и Writable в 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.
Типичные ошибки
Ловушки Readable и Writable: забытый backpressure (медленный consumer, быстрый producer = раздутая память); .pipe() без error-обработчиков (тихий провал); смешение object-mode и binary-mode streams; конверсия stream → Buffer ради JSON.parse (теряет смысл). for await (const chunk of stream) в современном Node — читается чище, чем event-обработчики.