راهنمای جامع Streams در Node.js (ماژول node:stream)

ماژول node:stream یکی از بنیادی‌ترین بخش‌های Node.js است و یک رابط انتزاعی برای کار با داده‌های جریان‌محور فراهم می‌کند. Streams برای مدیریت ورودی/خروجی‌های حجیم، درخواست‌های شبکه، خواندن/نوشتن فایل‌ها و انجام تبدیل‌های داده‌ای ضروری هستند. Streams نمونه‌هایی از EventEmitter بوده و در چهار نوع اصلی ارائه می‌شوند: Readable، Writable، Duplex و Transform.

Readable / Writable / Duplex / Transformpipeline / finishedBackpressureObject ModeCustom StreamsAsync IterationWeb Streams Interop

~3 دقیقه مطالعه · آخرین به‌روزرسانی ۹ دی ۱۴۰۴

1. معرفی Streams


Streams در Node.js امکان پردازش داده‌ها به‌صورت تکه‌تکه و پیوسته را فراهم می‌کنند. این رویکرد باعث کاهش مصرف حافظه و افزایش کارایی در عملیات I/O می‌شود.


2. انواع Stream


  • Readable: منبع داده (مثل fs.createReadStream یا پاسخ HTTP).
  • Writable: مقصد داده (مثل fs.createWriteStream یا درخواست HTTP).
  • Duplex: هم خواندنی و هم نوشتنی (مثل TCP Socket).
  • Transform: نوعی Duplex که داده را تغییر می‌دهد (مثل zlib).

3. دسترسی به ماژول


const stream = require('node:stream');
// یا
import stream from 'node:stream';

4. API مبتنی بر Promise


از طریق require('node:stream/promises') قابل دسترسی است.


4.1. pipeline()


برای اتصال چند Stream با مدیریت خطا و پاکسازی مناسب استفاده می‌شود.


await pipeline(
  fs.createReadStream('input.txt'),
  zlib.createGzip(),
  fs.createWriteStream('input.txt.gz')
);

4.2. finished()


منتظر پایان یک Stream می‌ماند.


await finished(readableStream);

5. Object Mode


در حالت عادی Streams فقط Buffer یا string را مدیریت می‌کنند. در Object Mode می‌توان هر مقدار جاوااسکریپتی (به‌جز null) را ارسال کرد.


const readable = new stream.Readable({
  objectMode: true,
  read() {
    this.push({ value: 42 });
    this.push(null);
  }
});

6. Buffering و Backpressure


  • هر Stream یک بافر داخلی دارد.
  • highWaterMark تعیین می‌کند چه زمانی Backpressure اعمال شود.
  • write() اگر false برگرداند یعنی باید منتظر رویداد drain بمانید.

7. API برای مصرف‌کنندگان


7.1. Writable Streams


  • write(chunk)
  • end()
  • رویدادها: drain, finish, error, pipe

7.2. Readable Streams


دو حالت دارند:

  • Paused: باید read() فراخوانی شود.
  • Flowing: رویداد data به‌صورت خودکار منتشر می‌شود.

7.3. Async Iteration


for await (const chunk of readable) {
  console.log(chunk);
}

8. Duplex و Transform


  • Duplex: خواندن و نوشتن مستقل.
  • Transform: خروجی بر اساس ورودی تغییر می‌کند.

9. API برای پیاده‌سازی Streamهای سفارشی


9.1. Writable سفارشی


class MyWritable extends stream.Writable {
  _write(chunk, encoding, callback) {
    // پردازش داده
    callback();
  }
}

9.2. Readable سفارشی


class Counter extends stream.Readable {
  _read() {
    this.push('data');
    this.push(null);
  }
}

9.3. Transform سفارشی


class Uppercase extends stream.Transform {
  _transform(chunk, encoding, callback) {
    callback(null, chunk.toString().toUpperCase());
  }
}

10. PassThrough


نوعی Transform که داده را بدون تغییر عبور می‌دهد.


11. توابع کمکی


  • stream.duplexPair(): ساخت یک جفت Duplex متصل.
  • stream.addAbortSignal(): اتصال AbortSignal به Stream.
  • Readable.from(): ساخت Stream از iterable.
  • سازگاری با Web Streams: toWeb() و fromWeb().

12. بهترین شیوه‌ها


  • استفاده از pipeline() برای زنجیره‌سازی.
  • مدیریت صحیح Backpressure.
  • استفاده از Object Mode فقط در صورت نیاز.
  • استفاده از async iteration برای خواندن داده.
  • فعال‌سازی Source Maps با --enable-source-maps.

نتیجه‌گیری


Streams ستون فقرات کارایی I/O در Node.js هستند. با تسلط بر آن‌ها می‌توان برنامه‌هایی مقیاس‌پذیر، سریع و کم‌مصرف ساخت که به‌خوبی با فایل‌ها، شبکه و داده‌های حجیم کار می‌کنند.


نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

آشنایی کامل با ماژول Cluster در Node.js و نحوه افزایش مقیاس‌پذیری سرور

ماژول Cluster در Node.js به توسعه‌دهندگان اجازه می‌دهد چندین پردازش همزمان ایجاد کنند که یک پورت سرور را به اشتراک می‌گذارند. این کار باعث استفاده بهتر از هسته‌های CPU و افزایش توان پردازش برنامه می‌شود. در این مقاله نحوه کار Cluster، مدیریت Workerها، تنظیمات مهم و مثال عملی را بررسی می‌کنیم.

ادامه

راهنمای جامع ماژول VM در Node.js (ماژول node:vm)

ماژول node:vm امکان کامپایل و اجرای کد جاوااسکریپت در کانتکست‌های ایزولهٔ V8 را فراهم می‌کند. این کانتکست‌ها مانند یک «سندباکس سبک» داخل برنامهٔ Node.js عمل می‌کنند و هرکدام globalThis مخصوص خود را دارند. این ماژول برای اجرای پویا، موتورهای قالب (Template Engines)، سیستم‌های افزونه (Plugin Systems)، REPLها و تست ایزولهٔ منطق بسیار مناسب است. اما نکتهٔ بسیار مهم: vm یک ابزار امنیتی نیست و نباید برای اجرای کدهای غیرقابل‌اعتماد استفاده شود.

ادامه

راهنمای جامع ماژول V8 در Node.js (ماژول node:v8)

راهنمای جامع ماژول V8 در Node.js (ماژول node:v8)

ادامه

راهنمای جامع Worker Threads در Node.js (ماژول node:worker_threads)

ماژول node:worker_threads امکان اجرای واقعی چندریسمانی (Multithreading) را در Node.js فراهم می‌کند. برخلاف مدل تک‌ریسمانی سنتی Node.js، Worker Threads اجازه می‌دهند کارهای سنگین CPU در ریسه‌های جداگانه اجرا شوند بدون اینکه حلقهٔ رویداد (Event Loop) مسدود شود. این ماژول از حافظهٔ اشتراکی، انتقال بدون کپی (Zero‑Copy)، کانال‌های پیام، Worker Pool، محدودیت منابع و ابزارهای همگام‌سازی پیشرفته پشتیبانی می‌کند. Worker Threads برای پردازش‌های محاسباتی سنگین ایده‌آل هستند، در حالی که I/O همچنان باید توسط ریسهٔ اصلی مدیریت شود.

ادامه

راهنمای جامع ماژول util در Node.js

ماژول node:util مجموعه‌ای از توابع کمکی قدرتمند برای استفاده در هستهٔ Node.js و همچنین توسعهٔ برنامه‌ها ارائه می‌دهد. این ماژول ابزارهایی برای دیباگ، بازرسی اشیا، تبدیل Callback ↔ Promise، قالب‌بندی رشته‌ها، بررسی انواع، مدیریت خطاها، رمزگذاری متن، پردازش MIME، پارس آرگومان‌های CLI، سیگنال‌های Abort، و ابزارهای متفرقه فراهم می‌کند. این ماژول یکی از جعبه‌ابزارهای اصلی و ضروری برای توسعه‌دهندگان Node.js است.

ادامه

راهنمای جامع ماژول URL در Node.js

ماژول node:url ابزارهایی برای تحلیل، ساخت، و دست‌کاری URLها در Node.js فراهم می‌کند. Node.js دو API برای کار با URL دارد: WHATWG URL API — استاندارد مدرن و سازگار با مرورگرها (توصیه‌شده). Legacy API — API قدیمی Node.js (غیرتوصیه‌شده). WHATWG URL API یک رابط تمیز، سازگار و قدرتمند برای کار با اجزای URL، پارامترهای query، الگوهای URL و حتی Blob URLها ارائه می‌دهد.

ادامه