JavaScriptda ma'lumotlarni samarali qayta ishlash uchun Web Streams APIni o'rganing. Ishlash unumdorligi va xotirani boshqarishni yaxshilash uchun oqimlarni yaratish, o'zgartirish va iste'mol qilishni o'rganing.
Web Streams API: JavaScriptda ma'lumotlarni qayta ishlashning samarali konveyerlari
Web Streams API JavaScriptda oqimli ma'lumotlar bilan ishlash uchun kuchli mexanizmni taqdim etadi, bu esa samarali va sezgir veb-ilovalar yaratish imkonini beradi. Butun ma'lumotlar to'plamini bir vaqtning o'zida xotiraga yuklash o'rniga, oqimlar sizga ma'lumotlarni bosqichma-bosqich qayta ishlashga imkon beradi, bu esa xotira sarfini kamaytiradi va ishlash samaradorligini oshiradi. Bu, ayniqsa, katta fayllar, tarmoq so'rovlari yoki real vaqtda uzatiladigan ma'lumotlar bilan ishlashda foydalidir.
Web oqimlari nima?
Asosan, Web Streams API uchta asosiy oqim turini taqdim etadi:
- ReadableStream: Fayl, tarmoq ulanishi yoki yaratilgan ma'lumotlar kabi ma'lumotlar manbasini ifodalaydi.
- WritableStream: Fayl, tarmoq ulanishi yoki ma'lumotlar bazasi kabi ma'lumotlar uchun manzilni ifodalaydi.
- TransformStream: ReadableStream va WritableStream o'rtasidagi o'zgartirish konveyerini ifodalaydi. U oqim orqali o'tayotgan ma'lumotlarni o'zgartirishi yoki qayta ishlashi mumkin.
Ushbu oqim turlari samarali ma'lumotlarni qayta ishlash konveyerlarini yaratish uchun birgalikda ishlaydi. Ma'lumotlar ReadableStream-dan, ixtiyoriy TransformStreams orqali va nihoyat WritableStream-ga oqadi.
Asosiy tushunchalar va terminologiya
- Bo'laklar (Chunks): Ma'lumotlar bo'laklar deb ataladigan alohida birliklarda qayta ishlanadi. Bo'lak har qanday JavaScript qiymati bo'lishi mumkin, masalan, satr, raqam yoki obyekt.
- Nazoratchilar (Controllers): Har bir oqim turi oqimni boshqarish usullarini taqdim etuvchi mos keladigan nazoratchi obyektiga ega. Masalan, ReadableStreamController sizga oqimga ma'lumotlarni navbatga qo'shish imkonini beradi, WritableStreamController esa kiruvchi bo'laklarni qayta ishlashga imkon beradi.
- Kanallar (Pipes): Oqimlarni
pipeTo()
vapipeThrough()
usullari yordamida bir-biriga ulash mumkin.pipeTo()
ReadableStream-ni WritableStream-ga ulaydi,pipeThrough()
esa ReadableStream-ni TransformStream-ga, so'ngra WritableStream-ga ulaydi. - Teskari bosim (Backpressure): Iste'molchiga ishlab chiqaruvchiga ko'proq ma'lumot olishga tayyor emasligini bildirish imkonini beruvchi mexanizm. Bu iste'molchining haddan tashqari yuklanishini oldini oladi va ma'lumotlarning barqaror tezlikda qayta ishlanishini ta'minlaydi.
ReadableStream yaratish
Siz ReadableStream()
konstruktoridan foydalanib ReadableStream yaratishingiz mumkin. Konstruktor argument sifatida obyektni qabul qiladi, u oqimning xatti-harakatlarini nazorat qilish uchun bir nechta usullarni belgilashi mumkin. Ulardan eng muhimi oqim yaratilganda chaqiriladigan start()
usuli va oqimga ko'proq ma'lumot kerak bo'lganda chaqiriladigan pull()
usulidir.
Bu yerda sonlar ketma-ketligini yaratadigan ReadableStream yaratish misoli keltirilgan:
const readableStream = new ReadableStream({
start(controller) {
let counter = 0;
function push() {
if (counter >= 10) {
controller.close();
return;
}
controller.enqueue(counter++);
setTimeout(push, 100);
}
push();
},
});
Ushbu misolda start()
usuli hisoblagichni ishga tushiradi va oqimga raqamni navbatga qo'yadigan va keyin qisqa pauzadan so'ng o'zini qayta chaqiradigan push()
funksiyasini belgilaydi. Hisoblagich 10 ga yetganda controller.close()
usuli chaqiriladi, bu esa oqim tugaganligini bildiradi.
ReadableStream-ni iste'mol qilish
ReadableStream-dan ma'lumotlarni iste'mol qilish uchun ReadableStreamDefaultReader
-dan foydalanishingiz mumkin. O'quvchi (reader) oqimdan bo'laklarni o'qish uchun usullarni taqdim etadi. Ulardan eng muhimi read()
usuli bo'lib, u ma'lumotlar bo'lagi va oqim tugaganligini ko'rsatuvchi bayroqni o'z ichiga olgan obyekt bilan hal qilinadigan promisni (promise) qaytaradi.
Bu yerda avvalgi misolda yaratilgan ReadableStream-dan ma'lumotlarni iste'mol qilish misoli keltirilgan:
const reader = readableStream.getReader();
async function read() {
const { done, value } = await reader.read();
if (done) {
console.log('Stream complete');
return;
}
console.log('Received:', value);
read();
}
read();
Ushbu misolda read()
funksiyasi oqimdan bir bo'lakni o'qiydi, uni konsolga chiqaradi va keyin oqim tugaguniga qadar o'zini qayta chaqiradi.
WritableStream yaratish
Siz WritableStream()
konstruktoridan foydalanib WritableStream yaratishingiz mumkin. Konstruktor argument sifatida obyektni qabul qiladi, u oqimning xatti-harakatlarini nazorat qilish uchun bir nechta usullarni belgilashi mumkin. Ulardan eng muhimlari - ma'lumotlar bo'lagi yozishga tayyor bo'lganda chaqiriladigan write()
usuli, oqim yopilganda chaqiriladigan close()
usuli va oqim bekor qilinganda chaqiriladigan abort()
usulidir.
Bu yerda har bir ma'lumot bo'lagini konsolga chiqaradigan WritableStream yaratish misoli keltirilgan:
const writableStream = new WritableStream({
write(chunk) {
console.log('Writing:', chunk);
return Promise.resolve(); // Indicate success
},
close() {
console.log('Stream closed');
},
abort(err) {
console.error('Stream aborted:', err);
},
});
Ushbu misolda write()
usuli bo'lakni konsolga chiqaradi va bo'lak muvaffaqiyatli yozilganda hal qilinadigan promisni qaytaradi. close()
va abort()
usullari oqim yopilganda yoki bekor qilinganda konsolga xabarlar chiqaradi.
WritableStream-ga yozish
WritableStream-ga ma'lumot yozish uchun WritableStreamDefaultWriter
-dan foydalanishingiz mumkin. Yozuvchi (writer) oqimga bo'laklarni yozish uchun usullarni taqdim etadi. Ulardan eng muhimi write()
usuli bo'lib, u ma'lumotlar bo'lagini argument sifatida qabul qiladi va bo'lak muvaffaqiyatli yozilganda hal qilinadigan promisni qaytaradi.
Bu yerda avvalgi misolda yaratilgan WritableStream-ga ma'lumot yozish misoli keltirilgan:
const writer = writableStream.getWriter();
async function writeData() {
await writer.write('Hello, world!');
await writer.close();
}
writeData();
Ushbu misolda writeData()
funksiyasi oqimga "Hello, world!" satrini yozadi va keyin oqimni yopadi.
TransformStream yaratish
Siz TransformStream()
konstruktoridan foydalanib TransformStream yaratishingiz mumkin. Konstruktor argument sifatida obyektni qabul qiladi, u oqimning xatti-harakatlarini nazorat qilish uchun bir nechta usullarni belgilashi mumkin. Ulardan eng muhimi - ma'lumotlar bo'lagi o'zgartirishga tayyor bo'lganda chaqiriladigan transform()
usuli va oqim yopilganda chaqiriladigan flush()
usulidir.
Bu yerda har bir ma'lumot bo'lagini katta harflarga o'tkazadigan TransformStream yaratish misoli keltirilgan:
const transformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
},
flush(controller) {
// Optional: Perform any final operations when the stream is closing
},
});
Ushbu misolda transform()
usuli bo'lakni katta harflarga o'tkazadi va uni nazoratchining navbatiga qo'shadi. flush()
usuli oqim yopilayotganda chaqiriladi va har qanday yakuniy operatsiyalarni bajarish uchun ishlatilishi mumkin.
Konveyerlarda TransformStreams-dan foydalanish
TransformStreams ma'lumotlarni qayta ishlash konveyerlarini yaratish uchun bir-biriga zanjir qilib bog'langanda eng foydali bo'ladi. Siz pipeThrough()
usulidan ReadableStream-ni TransformStream-ga, so'ngra WritableStream-ga ulash uchun foydalanishingiz mumkin.
Bu yerda ReadableStream-dan ma'lumotlarni o'qiydigan, TransformStream yordamida uni katta harflarga o'tkazadigan va keyin WritableStream-ga yozadigan konveyer yaratish misoli keltirilgan:
const readableStream = new ReadableStream({
start(controller) {
controller.enqueue('hello');
controller.enqueue('world');
controller.close();
},
});
const transformStream = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
},
});
const writableStream = new WritableStream({
write(chunk) {
console.log('Writing:', chunk);
return Promise.resolve();
},
});
readableStream.pipeThrough(transformStream).pipeTo(writableStream);
Ushbu misolda pipeThrough()
usuli readableStream
-ni transformStream
-ga ulaydi, so'ngra pipeTo()
usuli transformStream
-ni writableStream
-ga ulaydi. Ma'lumotlar ReadableStream-dan TransformStream orqali (bu yerda u katta harflarga o'tkaziladi) va keyin WritableStream-ga (bu yerda u konsolga chiqariladi) oqadi.
Teskari bosim (Backpressure)
Teskari bosim - bu Web Streams-dagi tez ishlab chiqaruvchining sekin iste'molchini haddan tashqari yuklashini oldini oladigan muhim mexanizmdir. Iste'molchi ma'lumotlar ishlab chiqarilayotgan tezlikka yetisha olmaganida, u ishlab chiqaruvchiga sekinlashishni bildira oladi. Bu oqimning nazoratchisi va o'quvchi/yozuvchi obyektlari orqali amalga oshiriladi.
ReadableStream-ning ichki navbati to'lganida, navbatda bo'sh joy paydo bo'lmaguncha pull()
usuli chaqirilmaydi. Xuddi shunday, WritableStream-ning write()
usuli faqat oqim ko'proq ma'lumot qabul qilishga tayyor bo'lgandagina hal qilinadigan promisni qaytarishi mumkin.
Teskari bosimni to'g'ri boshqarish orqali siz turli xil ma'lumotlar tezligi bilan ishlashda ham ma'lumotlarni qayta ishlash konveyerlaringizning mustahkam va samarali bo'lishini ta'minlay olasiz.
Qo'llash holatlari va misollar
1. Katta fayllarni qayta ishlash
Web Streams API katta fayllarni xotiraga to'liq yuklamasdan qayta ishlash uchun idealdir. Siz faylni bo'laklarga bo'lib o'qishingiz, har bir bo'lakni qayta ishlashingiz va natijalarni boshqa faylga yoki oqimga yozishingiz mumkin.
async function processFile(inputFile, outputFile) {
const readableStream = fs.createReadStream(inputFile).pipeThrough(new TextDecoderStream());
const writableStream = fs.createWriteStream(outputFile).pipeThrough(new TextEncoderStream());
const transformStream = new TransformStream({
transform(chunk, controller) {
// Misol: har bir satrni katta harflarga o'tkazish
const lines = chunk.split('\n');
lines.forEach(line => controller.enqueue(line.toUpperCase() + '\n'));
}
});
await readableStream.pipeThrough(transformStream).pipeTo(writableStream);
console.log('File processing complete!');
}
// Foydalanish misoli (Node.js talab qilinadi)
// const fs = require('fs');
// processFile('input.txt', 'output.txt');
2. Tarmoq so'rovlari bilan ishlash
Siz Web Streams API-dan tarmoq so'rovlaridan olingan ma'lumotlarni, masalan, API javoblari yoki server tomonidan yuborilgan hodisalarni qayta ishlash uchun foydalanishingiz mumkin. Bu sizga butun javob yuklab olinishini kutmasdan, ma'lumotlar kelishi bilanoq uni qayta ishlashni boshlash imkonini beradi.
async function fetchAndProcessData(url) {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const text = decoder.decode(value);
// Olingan ma'lumotlarni qayta ishlash
console.log('Received:', text);
}
} catch (error) {
console.error('Error reading from stream:', error);
} finally {
reader.releaseLock();
}
}
// Foydalanish misoli
// fetchAndProcessData('https://example.com/api/data');
3. Real vaqtda uzatiladigan ma'lumotlar
Web oqimlari, shuningdek, aksiya narxlari yoki sensor ko'rsatkichlari kabi real vaqtda uzatiladigan ma'lumotlar bilan ishlash uchun ham mos keladi. Siz ReadableStream-ni ma'lumot manbasiga ulab, kelayotgan ma'lumotlarni u kelishi bilanoq qayta ishlashingiz mumkin.
// Misol: Real vaqtda uzatiladigan ma'lumotlarni simulyatsiya qilish
const readableStream = new ReadableStream({
start(controller) {
let intervalId = setInterval(() => {
const data = Math.random(); // Sensor ko'rsatkichini simulyatsiya qilish
controller.enqueue(`Data: ${data.toFixed(2)}`);
}, 1000);
this.cancel = () => {
clearInterval(intervalId);
controller.close();
};
},
cancel() {
this.cancel();
}
});
const reader = readableStream.getReader();
async function readStream() {
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('Stream closed.');
break;
}
console.log('Received:', value);
}
} catch (error) {
console.error('Error reading from stream:', error);
} finally {
reader.releaseLock();
}
}
readStream();
// Oqimni 10 soniyadan so'ng to'xtatish
setTimeout(() => {readableStream.cancel()}, 10000);
Web Streams API-dan foydalanishning afzalliklari
- Yaxshilangan ishlash samaradorligi: Ma'lumotlarni bosqichma-bosqich qayta ishlash, xotira sarfini kamaytirish va sezgirlikni oshirish.
- Kengaytirilgan xotirani boshqarish: Butun ma'lumotlar to'plamini xotiraga yuklashdan saqlanish, ayniqsa katta fayllar yoki tarmoq oqimlari uchun foydali.
- Yaxshiroq foydalanuvchi tajribasi: Ma'lumotlarni tezroq qayta ishlash va ko'rsatishni boshlash, bu esa interaktiv va sezgir foydalanuvchi tajribasini ta'minlaydi.
- Soddalashtirilgan ma'lumotlarni qayta ishlash: TransformStreams yordamida modulli va qayta ishlatiladigan ma'lumotlarni qayta ishlash konveyerlarini yaratish.
- Teskari bosimni qo'llab-quvvatlash: Turli xil ma'lumotlar tezligini boshqarish va iste'molchilarning haddan tashqari yuklanishini oldini olish.
E'tiborga olish kerak bo'lgan jihatlar va eng yaxshi amaliyotlar
- Xatoliklarni qayta ishlash: Oqim xatolarini to'g'ri boshqarish va ilovaning kutilmagan xatti-harakatlarini oldini olish uchun mustahkam xatoliklarni qayta ishlashni joriy qiling.
- Resurslarni boshqarish: Xotira sizib chiqishini oldini olish uchun oqimlar endi kerak bo'lmaganda resurslarni to'g'ri bo'shating.
reader.releaseLock()
-dan foydalaning va oqimlarning mos ravishda yopilgan yoki bekor qilinganligiga ishonch hosil qiling. - Kodlash va dekodlash: Matnli ma'lumotlar bilan ishlashda to'g'ri belgilar kodlanishini ta'minlash uchun
TextEncoderStream
vaTextDecoderStream
-dan foydalaning. - Brauzer mosligi: Web Streams API-ni ishlatishdan oldin brauzer mosligini tekshiring va eski brauzerlar uchun polifillardan foydalanishni o'ylab ko'ring.
- Sinovdan o'tkazish: Ma'lumotlarni qayta ishlash konveyerlaringizning turli sharoitlarda to'g'ri ishlashini ta'minlash uchun ularni sinchkovlik bilan sinovdan o'tkazing.
Xulosa
Web Streams API JavaScriptda oqimli ma'lumotlar bilan ishlashning kuchli va samarali usulini taqdim etadi. Asosiy tushunchalarni tushunib, turli xil oqim turlaridan foydalanib, siz katta fayllar, tarmoq so'rovlari va real vaqtda uzatiladigan ma'lumotlar bilan osonlikcha ishlay oladigan mustahkam va sezgir veb-ilovalar yaratishingiz mumkin. Teskari bosimni joriy qilish va xatoliklarni qayta ishlash hamda resurslarni boshqarish bo'yicha eng yaxshi amaliyotlarga rioya qilish sizning ma'lumotlarni qayta ishlash konveyerlaringizning ishonchli va samarali bo'lishini ta'minlaydi. Veb-ilovalar rivojlanishda va tobora murakkab ma'lumotlar bilan ishlashda davom etar ekan, Web Streams API butun dunyodagi dasturchilar uchun muhim vositaga aylanadi.