Stream nima? Nodejsda streamlar bilan ishlash.

Habibov Ulug'bek
6 min readJul 21, 2024

--

Assalamu Alaykum bugun yana bir og`riqli mavzu streamlar mavzusini ko`rib chiqamiz.Stream nima va u nimaga kerak degan savollarga javob olamiz.
Bugungi maqolada :

  1. Stream nima ?
  2. Stream turlari
  3. Writable va readable streamlar haqida batafsil.
  4. Duplex va transform stream
  5. Piping

Stream nima ?

Xo`sh stream nima buni birinchi bo`lib Nodejs dokumentatsiyasidan qidirib ko`ramiz :

Stream bu uzatilayotgan ma’lumotlar bilan ishlash uchun mavhum interfeys

Bu streamning haqiqiy ma’nosi emas bu Nodejsdagi stream obyekti haqidagi ma’lumot .Stream ning to`liq tarif berilmaganligining sababi bu u computer science ning asosiy tushunchasi va buni dasturchi o`zi bilishi kerak deb hisoblanadi.

Xo`sh yana o`sha savolga qaytamiz stream nima ?

Stream bu qaysidir faylni bo`laklarga bo`lib uni uzatish bu yozish yoki o`qish ham bo`lishi yoki ikkalasi bir vaqtda bo`lishiyam mumkin.

Bu nimaga kerak sizda masalan 10Gb lik fayl bor buni qayergadir yozishingiz kerak ammo serveringizni xotirasi 1GB va u birdaniga hammasini o`qib yozolmaydi xotirasi yetmaydi .Bu holatda bizga stream yordam keladi. U 10 GB faylni bo`laklarga bo`lib o`qishga yordam beradi bu bo`laklar chunk deyiladi .Va siz buni yordamadi malum bir xotiradan oshmagan holda o`zidan bir necha baravar katta fayllarni ustida ammallar bajarishingiz mumkin.

chunk bu stream bo`layotgan holatdagi faylning bir qismi bo`lib u buffer bo`ladi yani 0 va 1 lardan iborat ma’lumot.

Bufferlar haqida ko`proq bilmoqchi bo`lsangiz boshqa maqolamga link.

Fact : chunk ning hajmi boshlang`ich(default) 64 kb bo`ladi

Streamlar qanchalik foydali ekanligini bilish uchun yana bir misol ko`ramiz .

Siz bir kodlangan fayl bor va unda maxfiy ma`lumotlar bor .Siz buni ochib oqishingiz zarur ammo u fayl juda katta .U faylning kodlanish usuli 11110000 o`rniga 1100 qo`yilgan ya’ni ham kodlangan ham hajmi kamaytirilgan .Siz buni osongina stream orqali chunklarga bo`lib va har bir chunkdagi malumotni ya’ni 1100 ni 11110000ga o`zgartirib yozishingiz mumkin va stream oxirida sizda koddan ochilgan to`liq fayl hosil bo`ladi .

encriptdan ochish misoli

Agarda ma’lumotlarni bo`lib uzatmoqchi bo`lsangiz stream eng yaxshi usul hisoblanadi.Undan foydalanishning asosiy 2ta sababi :

  1. Memory efficiency: Katta xotirali malumotlar bilan ishlashda katta xotira talab etilmaydi.
  2. Time efficiency: Ma’lumot bilan ishlashni boshlash juda kam vaqt oladi ,ya’ni ma’lumot bo`lsa ishlash boshlanadi .U xotiraga to`liq o`tkazilishi kutilmaydi.

Xo`sh bizda qanaqa stream turlari mavjud o`zi ?

Stream turlari

Bizda 4 xil stream turlari bo`lib ular har xil vazifalarni bajaradi . Bular :
1.Writable stream
2.Readable stream
3.Duplex stream
4.Transform stream

Writable streams

Writable stream bu nomidan ko`rinib turgandek yozuvchi stream hisoblanadi .Bu faylga , xotiraga yoki responsega yozish uchun ishlatilinishi mumkin.

Buni biz tushunarli bo`lishi uchun fs moduli orqali ko`rib chiqamiz .

Fs modulini import qilsangiz unda fs.createwriteStream() metodini ko`rishimiz mumkin va bu bizga writable stream yaratishga yordam beradi.

Biz qachonki fs.createwriteStream() metodini ishga tushursak u bizga stream obyektini qaytaradi va bu obyekt ichida internal buffer bo`ladi va uning hajmi default 16384 byte.Buni siz highWaterMark ga qiymat berish orqali o`zgartirishingiz mumkin .Shuningdek bu obyekda write metodi stream.write(data) bo`lib u malumotni yozishga yoradam beradi .Yana unda bir nechta eventlar va propertylar mavjud.

Qachonki biz stream.write(data) metodini ishga tushursak u biz bergan ma’lumotni internal bufferga yozib qoyadi .Va siz buni buffer to`lgancha amalga oshirishingiz mumkin. Buffer to`lgandan keyin stream uni ko`rsatilgan manzilga yozishga harakat qiladi .

const fs = require('fs');
const file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');

Agarda juda katta fayllarni yozishga harakat qilsak nima bo`ladi ?
U ham xuddi shu tarzda amalga oshadi ammo hisobga olishimiz kerak bo`lgan narsalar mavjud .Masalan agarda buffer to`lay deganda oxirgi ma’lumot bufferdagi bo`sh joydan ko`p bo`lsachi ? Bu holatda bu ma’lumot ikki qismga ajratiladi bufferga yetadigan bufferga yozilib ikkinchi qismi xotirada saqlanadi manimcha RAMda. Bunda ko`rishimiz mumkinki agar bufferni bo`shatmasda unga qayta qayta yozishda davom etsak u ortib qolgan ma’lumotlarni RAMga yozishda davom etadi va bu qachondir borib xotira yetishmasligidan Nodejs process tugatilishiga olib keladi .Xotira bo`shatilganligini bilish uchun drain eventini kutish kerak yani agarda write stream internal bufferni bo`shatsa drain eventini emit qiladi va men bo`shman deb bildiradi .

Va bizda shuningdek stream.writablelength fieldi bo`lib u bufferga qancha yozilganini ko`rsatadi tepada aytganimizdek agar u highWaterMark qiymatidan oshib ketsa performancega ta’sir qiladi .U drain eventidan keyin 0 ga qaytadi .

Readable stream

Readable stream ham nomidan bilinib turipti bu o`qish uchun ekanligi. Readable streamda ham biz qachonki fs.createReadStream() metodini ishga tushursak bu holatda ham stream obyektini olamiz unda 64kb internal buffer va bir necha event hamda propertylar olamiz. Biz stream.push(data) metodini orqali ma’lumotlarni o`qib hamda o`qilgan ma’lumotlarni bufferga joylashimiz mumkin . Buffer to`lgandan so`ng data eventini ishga tushuradi va biz shu yerdan unga yozilgan chunkni o`qib olishimiz mumkin .

var fs = require("fs");
var data = '';

var readerStream = fs.createReadStream('file.txt'); //Create a readable stream

readerStream.setEncoding('UTF8'); // Set the encoding to be utf8.

// Handle stream events --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});

readerStream.on('end',function() {
console.log(data);
});

readerStream.on('error', function(err) {
console.log(err.stack);
});

console.log("Program Ended");

Agar buffer to`lib qolsa u stream avtomatik pause holatiga o`tadi va buffer bo`shatilgandan so`ng yana qayta o`qishni davom ettiradi .

Endi yaratilganda stream pause holatida yani hali o`qishni boshlamagan bo`ladi.Unga data event handler qo`shilmaguncha u o`qishni boshlamaydi . Data handler qo`shilsagina o`qish boshlanadi .

O`qish tugatilganidan keyin end eventi ishga tushuriladi .

Duplex stream

Duplex stream bu bir vaqtda o`qish va yozish uchun ishlatilinadi .writable va readable streamda faqatgina bitta buffer bo`lsa ,duplex streamda 2 internal buffer bo`ladi biri o`qish uchun biri yozish uchun .Ular bir biridan alohida ajratilgan push metodi read internal bufferga , write metodi esa write internal bufferga ma’lumot uzatadi .

Note : Duplex stream ishlab chiqilishining asosoiy sababi Javascript multi inheritanceni qo`llab quvvatlamaydi shuning uchun birlashgan stream bizga kerak bo`ladi .

Transform stream

Qachonki biz ma’lumotni write internal bufferga va undan write internal bufferdan chiqarib olib buni boshqa joyga emas aynan readable streamning internal bufferiga yozilsa va bu ma’lumotni osongina o`qishni boshlash bilan qabul qilsak bu transform stream deyiladi .

Yanabiz read streamga ma’lumotni qo`yayotganda uning ustida bir necha ammallarni bajarishimiz mumkin . Transform stream bu duplex stream bo`lib(under the hood duplex ishlatadi) u faqatgina write internal bufferdan read bufferga to`gridan to`gri yozadi .

Piping

Xuddi biz aytgan drain eventini kutish yoki read streamni pause qilishning yana bir usuli mavjud bu piping bo`ladi bu ularni kodsiz avtomat ravishda qiladi .

Bu qanday bo`ladi readStream.pipe(writeStream) orqali read streamni write streamga ulanadi va pipe read streamdan chunklarni olib writable streamga yetkazib beradi.

const fs = require('fs');

// Creating a readable stream from a file
const readableStream = fs.createReadStream('input.txt');

// Creating a writable stream to a file
const writableStream = fs.createWriteStream('output.txt');

// Magic happens here!
readableStream.pipe(writableStream);

console.log('Piping complete! Check out output.txt.');

Ammo bu production kod uchun yaxshi hisoblanmaydi chunki unda error handling juda qiyin hamda bazan streamlar ochiq qolib ketishi mumkin .

pipeline()

Buning uchun Nodening 10 versiyasidan stream.pipeline() qo`shilgan bu ham pipeday ammo errorlar bilan ishlash ancha qulay va stream yopilishini taminlash hamda pipeline tugatilganda bajariladigan callback bilan taminlangan.

pipelindan foydalanilgan misol:

const { pipeline } = require('stream');
const fs = require('fs');
const zlib = require('zlib');

// Use the pipeline API to easily pipe a series of streams
// together and get notified when the pipeline is fully done.
// A pipeline to gzip a potentially huge video file efficiently:

pipeline(
fs.createReadStream('The.Matrix.1080p.mkv'),
zlib.createGzip(),
fs.createWriteStream('The.Matrix.1080p.mkv.gz'),
(err) => {
if (err) {
console.error('Pipeline failed', err);
} else {
console.log('Pipeline succeeded');
}
}
);

Tepada ko`rib chiqqanimizdek katta fayllarni bo`lib uzatish uchun streamlar bizga kerak va ularning har xil turlari borligi va har biri qanday tuzulganligini ko`rib chiqdik .

Agarda maqola yoqqan bo`lsa chapak chaling (ko`p chalsayam bo`ladi 50 tagacha).

Yana shunday maqolalar o`qishni xohlasangiz medium da follow tugmasini bosib qo`ying.

Xato va kamchiliklar uchun uzr !!!

linkedin.com => Ulug’bek Habibov | LinkedIn

telegram channel => @habibov_ulugbek

--

--

Habibov Ulug'bek
Habibov Ulug'bek

Written by Habibov Ulug'bek

Software Engineer | Backend Nodejs Developer

No responses yet