.pipe() chỉ làm một việc: chuyển dữ liệu và tôn trọng backpressure. Nó không lan truyền lỗi và không dọn dẹp.
Khi một stream trong chuỗi a.pipe(b).pipe(c) phát error:
- Các stream còn lại không bị destroy → file descriptor, socket, buffer vẫn treo.
- Nếu không gắn handler error cho từng stream, lỗi trở thành uncaught và làm chết tiến trình.
pipeline() gom cả ba việc đó: nối stream, destroy toàn bộ chuỗi khi có lỗi, và trả về một callback/promise duy nhất báo hoàn tất hay thất bại.
import { pipeline } from 'node:stream/promises'
import { createReadStream, createWriteStream } from 'node:fs'
import { createGzip } from 'node:zlib'
await pipeline(
createReadStream('input.log'),
createGzip(),
createWriteStream('input.log.gz'),
)Trường hợp hay gặp nhất trong production: client ngắt kết nối giữa chừng khi đang tải file.
Với .pipe(), sự kiện finish không bao giờ đến nên phần dọn dẹp không chạy → rò rỉ tích tụ. pipeline() phát hiện đóng sớm, ném ERR_STREAM_PREMATURE_CLOSE và destroy stream nguồn.