~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 هستند. با تسلط بر آنها میتوان برنامههایی مقیاسپذیر، سریع و کممصرف ساخت که بهخوبی با فایلها، شبکه و دادههای حجیم کار میکنند.
نوشته و پژوهش شده توسط دکتر شاهین صیامی