تعد التدفقات (Streams) مجموعات من البيانات التي قد لا تتوفر كلها دفعة واحدة، مما يتيح معالجة فعالة للملفات الضخمة وحمولات الشبكة دون استنزاف الذاكرة.
نظرة عامة على أنواع التدفقات
| النوع | الاتجاه | الوصف |
|---|---|---|
Readable |
قراءة فقط | مصدر يمكن قراءة واستهلاك البيانات منه |
Writable |
كتابة فقط | وجهة يمكن كتابة البيانات إليها |
Transform |
قراءة وكتابة | يقوم بتحويل أو تعديل البيانات أثناء مرورها عبره |
Duplex |
قراءة وكتابة | قابل للقراءة والكتابة بقنوات مستقلة (مثل مقبس TCP) |
خط الأنابيب وواجهة stream/promises الحديثة
يوفر Node.js الحديث دالة pipeline لربط التدفقات بأمان مع معالجة الأخطاء وتنظيف الموارد تلقائياً:
const { pipeline } = require('stream/promises');
const fs = require('fs');
const zlib = require('zlib');
async function compressFile() {
await pipeline(
fs.createReadStream('source.tar'),
zlib.createGzip(),
fs.createWriteStream('source.tar.gz')
);
console.log('اكتمل الضغط بنجاح');
}
إنشاء تدفقات مخصصة
1. تدفق قراءة مخصص (Readable)
const { Readable } = require('stream');
function createTimestampStream() {
let count = 0;
return new Readable({
objectMode: true,
read() {
if (count >= 5) {
this.push(null); // نهاية التدفق
} else {
this.push({ id: ++count, time: new Date() });
}
}
});
}
2. تدفق تحويل مخصص (Transform)
const { Transform } = require('stream');
const uppercaseTransformer = new Transform({
transform(chunk, encoding, callback) {
const transformed = chunk.toString().toUpperCase();
callback(null, transformed);
}
});
3. تدفق كتابة مخصص (Writable)
const { Writable } = require('stream');
const consoleWriter = new Writable({
objectMode: true,
write(chunk, encoding, callback) {
console.log('كتابة القطعة:', chunk);
callback();
}
});
الوضع الجاري مقابل الوضع المتوقف (Flowing vs Paused)
تعمل تدفقات القراءة في الوضع المتوقف أو الوضع الجاري تلقائياً:
const stream = fs.createReadStream('data.csv');
// إضافة مستمع 'data' ينشط الوضع الجاري تلقائياً
stream.on('data', (chunk) => {
console.log(`تم استلام ${chunk.length} بايت`);
});
// التحكم الصريح في التدفق
stream.pause(); // تعليق الأحداث مؤقتاً
stream.resume(); // استئناف أحداث التدفق
أحداث التدفقات (Stream Events)
| الحدث | ينطبق على | شرط الإطلاق |
|---|---|---|
data |
Readable |
يتم إطلاقه عندما تصبح قطعة بيانات جاهزة للاستهلاك |
end |
Readable |
يتم إطلاقه عند عدم توفر المزيد من البيانات للقراءة |
finish |
Writable |
يتم إطلاقه عند اكتمال كتابة وتفريغ جميع البيانات |
error |
All | يتم إطلاقه عند حدوث خطأ غير معالج في التدفق |
close |
All | يتم إطلاقه عند إغلاق الواصف الأساسي للتدفق |