برنامه نویسی 185 بازدید

برای مدیریت و دستکاری داده‌های استریمی مانند ویدئو، فایل‌های بزرگ و غیره در Node.js از استریم (Stream) استفاده می‌کنیم. ماژول streams در این محیط اجرایی، همه استریم‌ها را مدیریت می‌کند. در این مقاله روی مفاهیمی مرتبط با استریم و بافر در Node.js تمرکز خواهیم داشت.

انواع استریم

در Node.js چهار نوع متفاوت از استریم وجود دارد:

  • استریم‌های خواندنی (Readable streams): برای ایجاد استریم‌های داده جهت خواندن استفاده می‌شوند. برای نمونه می‌توان یک فایل بزرگ را به صورت بخش به بخش خواند.
  • استریم‌های نوشتنی (Writable streams): برای ایجاد یک استریم از داده‌ها برای نوشتن استفاده می‌شوند. برای نمونه می‌توانیم مقادیر زیادی از داده‌ها را در یک فایل بنویسیم.
  • استریم‌های داپلکس (Duplex streams): برای ایجاد یک استریم استفاده می‌شود که همزمان هم خواندنی و هم نوشتنی است.
  • استریم‌های تبدیلی (Transform streams): برای ایجاد استریمی استفاده می‌شود که خواندنی و نوشتنی است، اما داده‌ها پس از نوشته شدن در استریم قابل ویرایش هستند. فرض کنید می‌خواهید داده‌ها را از سوی کلاینت و سرور پیش از ارسال درخواست، فشرده‌سازی کنید.

بافرها در استریم‌ها

استریم‌ها بر مبنای مفهومی به نام «بافر» (buffer) عمل می‌کنند. منظور از بافر حافظه موقتی است که استریم برای نگهداری برخی داده‌ها تا زمان مصرف اشغال می‌کند. اندازه بافر در یک استریم بر اساس مشخصه highWatermark در آن وهله از استریم تعیین می‌شود که عدد مربوطه نشان‌دهنده اندازه بافر برحسب بایت است.

حافظه بافر در Node به صورت پیش‌فرض روی String و Buffer کار می‌کند. می‌توان حافظه بافر را روی اشیای جاوا اسکریپت نیز استفاده کرد. به این منظور باید مشخصه objectMode روی شیء استریم به صورت true تنظیم شود. اگر تلاش کنیم تا داده‌ها به استریم push کنیم، داده‌ها به بافر استریم push می‌شوند. داده‌ای push شده در بافر در آنجا می‌مانند تا این که مصرف شوند. اگر بافر پر شده باشد و تلاش کنیم تا داده‌ها را به بافر push کنیم، استریم آن داده‌ها را نمی‌پذیرد و مقدار false برای عمل push بازگشت می‌دهد.

استریم‌ها و EventEmitters

استریم‌ها اقدام به بسط EventEmitters می‌کنند. استریم‌های Node.js کلاس EventEmitters را بسط می‌دهند. می‌توان به رویدادهایی مانند data و end در استریم‌ها گوش داد. برای گوش کردن به یک رویداد باید از تابع ()stream.on که در استریم موجود است استفاده کنیم. برای کسب اطلاعات بیشتر در مورد EventEmitters در Node.js پیشنهاد می‌کنیم این مقاله (+) را مطالعه کنید.

استریم‌های خواندن در Node.js

استریمی که برای خواندن داده‌های استریم‌شده استفاده می‌شود به نام «استریم خواندن» (Read Stream) نامیده می‌شود. استریم خواندن می‌تواند فایل را از سرور بخواند یا یک ویدئو را به صورت آنلاین استریم کند.

برای مقایسه می‌توانید استریم‌های خواندن را مانند یک شیر آب تصور کنید. از شیر آب، آب جریان می‌یابد (در این مورد داده) و از سوی فردی مصرف می‌شود. در این بخش یک استریم خواندن ایجاد می‌کنیم که فایل متنی بزرگی را ایجاد می‌کند تا عملکرد آن را مشاهده کنیم.

زمانی که آن را اجرا کنیم، خروجی زیر به دست می‌آید:

به این ترتیب داده‌های بافر را به دست آورده‌ایم که چیزی به جز داده‌های بایتی محتوایی که در حافظه بافر استریم قرار گرفته‌اند نیست.

استریم و بافر در Node.js

ایجاد مکث و یا از سرگیری فعالیت یک استریم خواندن

یک استریم را در Node.js می‌توان با فراخوانی تابع‌های ()pause و ()resume روی استریم به حالت مکث برده یا فعالیت آن را از سر گرفت. در نتیجه فراخوانی تابع ()pause، رویداد data تحریک نمی‌شود تا این که دوباره تابع ()resume استریم را فراخوانی کنیم.

استریم‌های Flowing و غیر Flowing

دو نوع استریم خواندنی وجود دارند:

  • استریم Flowing: استریمی است که ارسال داده‌ها را به صورت پیوسته انجام می‌دهد و امکان شنیدن مستقیم با استفاده از رویداد data روی استریم وجود دارد.
  • استریم غیر Flowing: استریمی است که داده‌ها را به صورت خودکار push نمی‌کند. به جای آن استریم داده‌ها را در بافر ذخیره می‌کند و باید متد ()read استریم را فراخوانی کنیم تا آن را بخوانیم.

کد فوق مثالی از استریم Flowing است که در آن به رویداد data استریم گوش می‌دهیم و شنونده به صورت خودکار هر بار که داده‌های جدیدی از استریم می‌رسند، تحریک می‌شود.

در ادامه مثالی ساده از استریم‌های غیر Flowing می‌بینید:

هنگامی که کد فوق را اجرا کنیم، خروجی زیر به دست می‌آید:

<Buffer 4c 6f 72 65 6d 20 69 70 73 75>

طرز کار آن چگونه است؟

دلیل خروجی فوق این است که استریم خواندن با استفاده از متد createReadStream از ماژول FS کار می‌کند. به محض این که استریم ایجاد شود، داده‌های فایل شروع به استریم شدن به متغیر استریم می‌کنند. همچنین با استفاده از متد setTimeout می‌توانیم امکان تعیین مقداری زمان برای استریم شدن بدهیم تا مقداری از داده‌ها در بافر آن پر شود.

پس از 10 میلی‌ثانیه یک Callback به نام setTimeout اجرا می‌شود و 10 بایت نخست بافر را با استفاده از متد read()‎ که با 10 (بایت) از یک آرگومان فراخوانی می‌شود را می‌خواند.

مدیریت بافر به وسیله استریم خواندنی

در کد فوق، اگر تابع ()read را بار دیگر پس از console.log(data) فراخوانی کنیم، و داده‌های جدید را پرینت کنیم، می‌بینیم که داده‌ها از لاگ قبلی متفاوت هستند:

در کد فوق، خروجی به صورت زیر است:

<Buffer 4c 6f 72 65 6d 20 69 70 73 75>
<Buffer 6d 20 64 6f 6c 6f 72 20 73 69>

مقادیر لاگ شده به این دلیل متفاوت هستند که بافر داده‌ها را پس از خوانده شدن از سوی مصرف‌کننده را حذف می‌کند. از این رو در فراخوانی نخست متد ()read، ده بایت نخست داده‌های بافر را می‌خوانیم و در فراخوانی دوم متد ()read یازدهمین تا بیستمین بایت داده‌های واقعی که در حال حاضر در 10 بایت نخست بافر قرار دارند خوانده می‌شوند. بدین ترتیب به پایان این مقاله در مورد استریم‌های خواندن در Node.js می‌رسیم.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

میثم لطفی (+)

«میثم لطفی» دانش‌آموخته ریاضیات و شیفته فناوری به خصوص در حوزه رایانه است. وی در حال حاضر علاوه بر پیگیری علاقه‌مندی‌هایش در رشته‌های برنامه‌نویسی، کپی‌رایتینگ و محتوای چندرسانه‌ای، در زمینه نگارش مقالاتی با محوریت نرم‌افزار نیز با مجله فرادرس همکاری دارد.

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *