O'zbek

Oqimli qayta ishlashda inqilob qilish uchun JavaScript Asinxron Iterator Yordamchilarini o'rganing. map, filter, take, drop va boshqalar yordamida asinxron ma'lumotlar oqimlarini samarali boshqarishni o'rganing.

JavaScript Asinxron Iterator Yordamchilari: Zamonaviy Ilovalar Uchun Kuchli Oqimli Qayta Ishlash

Zamonaviy JavaScript dasturlashda asinxron ma'lumotlar oqimlari bilan ishlash keng tarqalgan talabdir. API'dan ma'lumotlarni olish, katta fayllarni qayta ishlash yoki real vaqtdagi hodisalarni boshqarishdan qat'iy nazar, asinxron ma'lumotlarni samarali boshqarish juda muhim. JavaScript'ning Asinxron Iterator Yordamchilari ushbu oqimlarni qayta ishlashning kuchli va oqlangan usulini taqdim etadi, bu esa ma'lumotlarni manipulyatsiya qilish uchun funksional va kompozitsion yondashuvni taklif qiladi.

Asinxron Iteratorlar va Asinxron Iterabllar nima?

Asinxron Iterator Yordamchilariga sho'ng'ishdan oldin, uning asosidagi tushunchalarni tushunib olaylik: Asinxron Iteratorlar va Asinxron Iterabllar.

Asinxron Iterable - bu o'z qiymatlari bo'yicha asinxron ravishda iteratsiya qilish usulini belgilaydigan obyekt. U buni @@asyncIterator metodini amalga oshirish orqali bajaradi, bu esa Asinxron Iteratorni qaytaradi.

Asinxron Iterator - bu next() metodini taqdim etadigan obyekt. Bu metod ikkita xususiyatga ega obyekt bilan yakunlanadigan promise'ni qaytaradi:

Mana oddiy misol:


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 500)); // Asinxron operatsiyani simulyatsiya qilish
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  for await (const value of asyncIterable) {
    console.log(value); // Natija: 1, 2, 3, 4, 5 (har biri orasida 500ms kechikish bilan)
  }
})();

Ushbu misolda, generateSequence asinxron ravishda raqamlar ketma-ketligini hosil qiluvchi asinxron generator funksiyasidir. for await...of tsikli asinxron iterabledan qiymatlarni iste'mol qilish uchun ishlatiladi.

Asinxron Iterator Yordamchilarini Tanishtirish

Asinxron Iterator Yordamchilari Asinxron Iteratorlarning funksionalligini kengaytirib, asinxron ma'lumotlar oqimlarini o'zgartirish, filtrlash va manipulyatsiya qilish uchun bir qator metodlarni taqdim etadi. Ular funksional va kompozitsion dasturlash uslubini yoqib, murakkab ma'lumotlarni qayta ishlash quvurlarini qurishni osonlashtiradi.

Asosiy Asinxron Iterator Yordamchilariga quyidagilar kiradi:

Keling, har bir yordamchini misollar bilan ko'rib chiqaylik.

map()

map() yordamchisi asinxron iterablening har bir elementini taqdim etilgan funksiya yordamida o'zgartiradi. U o'zgartirilgan qiymatlar bilan yangi asinxron iterable qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const doubledIterable = asyncIterable.map(x => x * 2);

(async () => {
  for await (const value of doubledIterable) {
    console.log(value); // Natija: 2, 4, 6, 8, 10 (100ms kechikish bilan)
  }
})();

Ushbu misolda, map(x => x * 2) ketma-ketlikdagi har bir raqamni ikki barobarga oshiradi.

filter()

filter() yordamchisi asinxron iterabledan taqdim etilgan shart (predikat funksiya) asosida elementlarni tanlaydi. U faqat shartni qanoatlantiradigan elementlarni o'z ichiga olgan yangi asinxron iterable qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(10);

const evenNumbersIterable = asyncIterable.filter(x => x % 2 === 0);

(async () => {
  for await (const value of evenNumbersIterable) {
    console.log(value); // Natija: 2, 4, 6, 8, 10 (100ms kechikish bilan)
  }
})();

Ushbu misolda, filter(x => x % 2 === 0) ketma-ketlikdan faqat juft raqamlarni tanlaydi.

take()

take() yordamchisi asinxron iterabledan birinchi N ta elementni qaytaradi. U faqat belgilangan miqdordagi elementlarni o'z ichiga olgan yangi asinxron iterable qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const firstThreeIterable = asyncIterable.take(3);

(async () => {
  for await (const value of firstThreeIterable) {
    console.log(value); // Natija: 1, 2, 3 (100ms kechikish bilan)
  }
})();

Ushbu misolda, take(3) ketma-ketlikdan birinchi uchta raqamni tanlaydi.

drop()

drop() yordamchisi asinxron iterabledan birinchi N ta elementni o'tkazib yuboradi va qolganini qaytaradi. U qolgan elementlarni o'z ichiga olgan yangi asinxron iterable qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

const afterFirstTwoIterable = asyncIterable.drop(2);

(async () => {
  for await (const value of afterFirstTwoIterable) {
    console.log(value); // Natija: 3, 4, 5 (100ms kechikish bilan)
  }
})();

Ushbu misolda, drop(2) ketma-ketlikdan birinchi ikkita raqamni o'tkazib yuboradi.

toArray()

toArray() yordamchisi butun asinxron iterableni iste'mol qiladi va barcha elementlarni massivga yig'adi. U barcha elementlarni o'z ichiga olgan massiv bilan yakunlanadigan promise qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const numbersArray = await asyncIterable.toArray();
  console.log(numbersArray); // Natija: [1, 2, 3, 4, 5]
})();

Ushbu misolda, toArray() ketma-ketlikdagi barcha raqamlarni massivga yig'adi.

forEach()

forEach() yordamchisi asinxron iterabledagi har bir element uchun taqdim etilgan funksiyani bir marta bajaradi. U yangi asinxron iterable qaytarmaydi, u funksiyani qo'shimcha ta'sir (side-effect) sifatida bajaradi. Bu jurnalga yozish yoki UI'ni yangilash kabi operatsiyalarni bajarish uchun foydali bo'lishi mumkin.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(3);

(async () => {
  await asyncIterable.forEach(value => {
    console.log("Qiymat:", value);
  });
  console.log("forEach yakunlandi");
})();
// Natija: Qiymat: 1, Qiymat: 2, Qiymat: 3, forEach yakunlandi

some()

some() yordamchisi asinxron iterabledagi kamida bitta element taqdim etilgan funksiya tomonidan amalga oshirilgan testdan o'tishini tekshiradi. U mantiqiy qiymat (agar kamida bitta element shartni qanoatlantirsa true, aks holda false) bilan yakunlanadigan promise qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const hasEvenNumber = await asyncIterable.some(x => x % 2 === 0);
  console.log("Juft son mavjud:", hasEvenNumber); // Natija: Juft son mavjud: true
})();

every()

every() yordamchisi asinxron iterabledagi barcha elementlar taqdim etilgan funksiya tomonidan amalga oshirilgan testdan o'tishini tekshiradi. U mantiqiy qiymat (agar barcha elementlar shartni qanoatlantirsa true, aks holda false) bilan yakunlanadigan promise qaytaradi.


async function* generateSequence(end) {
  for (let i = 2; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(4);

(async () => {
  const areAllEven = await asyncIterable.every(x => x % 2 === 0);
  console.log("Hammasi juftmi:", areAllEven); // Natija: Hammasi juftmi: true
})();

find()

find() yordamchisi asinxron iterabledagi taqdim etilgan sinov funksiyasini qanoatlantiradigan birinchi elementni qaytaradi. Agar hech qanday qiymat sinov funksiyasini qanoatlantirmasa, undefined qaytariladi. U topilgan element yoki undefined bilan yakunlanadigan promise qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const firstEven = await asyncIterable.find(x => x % 2 === 0);
  console.log("Birinchi juft son:", firstEven); // Natija: Birinchi juft son: 2
})();

reduce()

reduce() yordamchisi foydalanuvchi tomonidan taqdim etilgan "reducer" qayta chaqiruv funksiyasini asinxron iterablening har bir elementi uchun ketma-ketlikda bajaradi, oldingi elementdagi hisoblashdan qaytgan qiymatni o'tkazadi. Barcha elementlar bo'yicha reducerni ishga tushirishning yakuniy natijasi bitta qiymatdir. U yakuniy to'plangan qiymat bilan yakunlanadigan promise qaytaradi.


async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(5);

(async () => {
  const sum = await asyncIterable.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
  console.log("Yig'indi:", sum); // Natija: Yig'indi: 15
})();

Amaliy Misollar va Qo'llash Holatlari

Asinxron Iterator Yordamchilari turli xil stsenariylarda qimmatlidir. Keling, ba'zi amaliy misollarni ko'rib chiqaylik:

1. Oqimli API'dan Ma'lumotlarni Qayta Ishlash

Tasavvur qiling, siz oqimli API'dan ma'lumotlarni qabul qiladigan real vaqtdagi ma'lumotlarni vizualizatsiya qilish boshqaruv panelini yaratayapsiz. API yangilanishlarni uzluksiz yuboradi va siz so'nggi ma'lumotlarni ko'rsatish uchun ushbu yangilanishlarni qayta ishlashingiz kerak.


async function* fetchDataFromAPI(url) {
  let response = await fetch(url);

  if (!response.body) {
    throw new Error("ReadableStream bu muhitda qo'llab-quvvatlanmaydi");
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        break;
      }
      const chunk = decoder.decode(value);
      // API JSON obyektlarini yangi qatorlar bilan ajratilgan holda yuboradi deb faraz qilamiz
      const lines = chunk.split('\n');
      for (const line of lines) {
        if (line.trim() !== '') {
          yield JSON.parse(line);
        }
      }
    }
  } finally {
    reader.releaseLock();
  }
}

const apiURL = 'https://example.com/streaming-api'; // O'zingizning API URL manzilingiz bilan almashtiring
const dataStream = fetchDataFromAPI(apiURL);

// Ma'lumotlar oqimini qayta ishlash
(async () => {
  for await (const data of dataStream.filter(item => item.type === 'metric').map(item => ({ timestamp: item.timestamp, value: item.value }))) {
    console.log('Qayta ishlangan ma\'lumot:', data);
    // Boshqaruv panelini qayta ishlangan ma'lumotlar bilan yangilash
  }
})();

Ushbu misolda, fetchDataFromAPI oqimli API'dan ma'lumotlarni oladi, JSON obyektlarini tahlil qiladi va ularni asinxron iterable sifatida qaytaradi. filter yordamchisi faqat metrikalarni tanlaydi va map yordamchisi boshqaruv panelini yangilashdan oldin ma'lumotlarni kerakli formatga o'zgartiradi.

2. Katta Fayllarni O'qish va Qayta Ishlash

Aytaylik, siz mijozlar ma'lumotlarini o'z ichiga olgan katta CSV faylini qayta ishlashingiz kerak. Butun faylni xotiraga yuklash o'rniga, uni qismlarga bo'lib qayta ishlash uchun Asinxron Iterator Yordamchilaridan foydalanishingiz mumkin.


async function* readLinesFromFile(filePath) {
  const file = await fsPromises.open(filePath, 'r');

  try {
    let buffer = Buffer.alloc(1024);
    let fileOffset = 0;
    let remainder = '';

    while (true) {
      const { bytesRead } = await file.read(buffer, 0, buffer.length, fileOffset);
      if (bytesRead === 0) {
        if (remainder) {
          yield remainder;
        }
        break;
      }

      fileOffset += bytesRead;
      const chunk = buffer.toString('utf8', 0, bytesRead);
      const lines = chunk.split('\n');

      lines[0] = remainder + lines[0];
      remainder = lines.pop() || '';

      for (const line of lines) {
        yield line;
      }
    }
  } finally {
    await file.close();
  }
}

const filePath = './customer_data.csv'; // O'zingizning fayl yo'lingiz bilan almashtiring
const lines = readLinesFromFile(filePath);

// Qatorlarni qayta ishlash
(async () => {
  for await (const customerData of lines.drop(1).map(line => line.split(',')).filter(data => data[2] === 'USA')) {
    console.log('AQShdan mijoz:', customerData);
    // AQShdan bo'lgan mijoz ma'lumotlarini qayta ishlash
  }
})();

Ushbu misolda, readLinesFromFile faylni qatorma-qator o'qiydi va har bir qatorni asinxron iterable sifatida qaytaradi. drop(1) yordamchisi sarlavha qatorini o'tkazib yuboradi, map yordamchisi qatorni ustunlarga ajratadi va filter yordamchisi faqat AQShdan bo'lgan mijozlarni tanlaydi.

3. Real Vaqtdagi Hodisalarni Boshqarish

Asinxron Iterator Yordamchilari WebSockets kabi manbalardan keladigan real vaqtdagi hodisalarni boshqarish uchun ham ishlatilishi mumkin. Siz hodisalar kelishi bilan ularni chiqaradigan asinxron iterable yaratishingiz va keyin bu hodisalarni qayta ishlash uchun yordamchilardan foydalanishingiz mumkin.


async function* createWebSocketStream(url) {
  const ws = new WebSocket(url);

  yield new Promise((resolve, reject) => {
      ws.onopen = () => {
          resolve();
      };
      ws.onerror = (error) => {
          reject(error);
      };
  });

  try {
    while (ws.readyState === WebSocket.OPEN) {
      yield new Promise((resolve, reject) => {
        ws.onmessage = (event) => {
          resolve(JSON.parse(event.data));
        };
        ws.onerror = (error) => {
          reject(error);
        };
        ws.onclose = () => {
           resolve(null); // Ulanish yopilganda null bilan yakunlash
        }
      });

    }
  } finally {
    ws.close();
  }
}

const websocketURL = 'wss://example.com/events'; // O'zingizning WebSocket URL manzilingiz bilan almashtiring
const eventStream = createWebSocketStream(websocketURL);

// Hodisalar oqimini qayta ishlash
(async () => {
  for await (const event of eventStream.filter(event => event.type === 'user_login').map(event => ({ userId: event.userId, timestamp: event.timestamp }))) {
    console.log('Foydalanuvchi kirish hodisasi:', event);
    // Foydalanuvchi kirish hodisasini qayta ishlash
  }
})();

Ushbu misolda, createWebSocketStream WebSocket'dan qabul qilingan hodisalarni chiqaradigan asinxron iterable yaratadi. filter yordamchisi faqat foydalanuvchi kirish hodisalarini tanlaydi va map yordamchisi ma'lumotlarni kerakli formatga o'zgartiradi.

Asinxron Iterator Yordamchilaridan Foydalanishning Afzalliklari

Brauzer va Ishga Tushirish Muhiti Qo'llab-quvvatlashi

Asinxron Iterator Yordamchilari hali ham JavaScript'da nisbatan yangi xususiyatdir. 2024-yil oxiriga kelib, ular TC39 standartlashtirish jarayonining 3-bosqichida, ya'ni yaqin kelajakda standartlashtirilishi ehtimoli yuqori. Biroq, ular hali barcha brauzerlarda va Node.js versiyalarida tabiiy ravishda qo'llab-quvvatlanmaydi.

Brauzer Qo'llab-quvvatlashi: Chrome, Firefox, Safari va Edge kabi zamonaviy brauzerlar asta-sekin Asinxron Iterator Yordamchilarini qo'llab-quvvatlashni qo'shmoqda. Qaysi brauzerlar bu xususiyatni qo'llab-quvvatlashini ko'rish uchun Can I use... kabi veb-saytlardagi so'nggi brauzer mosligi ma'lumotlarini tekshirishingiz mumkin.

Node.js Qo'llab-quvvatlashi: Node.js'ning so'nggi versiyalari (v18 va undan yuqori) Asinxron Iterator Yordamchilari uchun eksperimental qo'llab-quvvatlashni taqdim etadi. Ulardan foydalanish uchun siz Node.js'ni --experimental-async-iterator flagi bilan ishga tushirishingiz kerak bo'lishi mumkin.

Polifillar: Agar siz Asinxron Iterator Yordamchilarini ularni tabiiy ravishda qo'llab-quvvatlamaydigan muhitlarda ishlatishingiz kerak bo'lsa, polifilldan foydalanishingiz mumkin. Polifill - bu yetishmayotgan funksionallikni ta'minlaydigan kod parchasi. Asinxron Iterator Yordamchilari uchun bir nechta polifill kutubxonalari mavjud; mashhur variantlardan biri core-js kutubxonasidir.

Maxsus Asinxron Iteratorlarni Amalga Oshirish

Asinxron Iterator Yordamchilari mavjud asinxron iterabllarni qayta ishlashning qulay usulini taqdim etsa-da, ba'zida o'zingizning maxsus asinxron iteratorlaringizni yaratishingiz kerak bo'lishi mumkin. Bu sizga ma'lumotlar bazalari, API'lar yoki fayl tizimlari kabi turli manbalardan ma'lumotlarni oqimli tarzda boshqarish imkonini beradi.

Maxsus asinxron iterator yaratish uchun siz obyektda @@asyncIterator metodini amalga oshirishingiz kerak. Bu metod next() metodiga ega bo'lgan obyektni qaytarishi kerak. next() metodi value va done xususiyatlariga ega obyekt bilan yakunlanadigan promise'ni qaytarishi kerak.

Mana sahifalangan API'dan ma'lumotlarni oladigan maxsus asinxron iterator misoli:


async function* fetchPaginatedData(baseURL) {
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const url = `${baseURL}?page=${page}`;
    const response = await fetch(url);
    const data = await response.json();

    if (data.results.length === 0) {
      hasMore = false;
      break;
    }

    for (const item of data.results) {
      yield item;
    }

    page++;
  }
}

const apiBaseURL = 'https://api.example.com/data'; // O'zingizning API URL manzilingiz bilan almashtiring
const paginatedData = fetchPaginatedData(apiBaseURL);

// Sahifalangan ma'lumotlarni qayta ishlash
(async () => {
  for await (const item of paginatedData) {
    console.log('Element:', item);
    // Elementni qayta ishlash
  }
})();

Ushbu misolda, fetchPaginatedData sahifalangan API'dan ma'lumotlarni oladi va har bir elementni olingan zahoti qaytaradi. Asinxron iterator sahifalash mantiqini boshqaradi, bu esa ma'lumotlarni oqimli tarzda iste'mol qilishni osonlashtiradi.

Potentsial Qiyinchiliklar va Mulohazalar

Asinxron Iterator Yordamchilari ko'plab afzalliklarni taklif qilsa-da, ba'zi potentsial qiyinchiliklar va mulohazalardan xabardor bo'lish muhim:

Asinxron Iterator Yordamchilaridan Foydalanishning Eng Yaxshi Amaliyotlari

Asinxron Iterator Yordamchilaridan maksimal darajada foydalanish uchun quyidagi eng yaxshi amaliyotlarni ko'rib chiqing:

Ilg'or Texnikalar

Maxsus Yordamchilarni Yaratish

Siz mavjud yordamchilarni birlashtirib yoki noldan yangilarini yaratib, o'zingizning maxsus asinxron iterator yordamchilaringizni yaratishingiz mumkin. Bu sizga funksionallikni o'z ehtiyojlaringizga moslashtirish va qayta ishlatiladigan komponentlarni yaratish imkonini beradi.


async function* takeWhile(asyncIterable, predicate) {
  for await (const value of asyncIterable) {
    if (!predicate(value)) {
      break;
    }
    yield value;
  }
}

// Foydalanish misoli:
async function* generateSequence(end) {
  for (let i = 1; i <= end; i++) {
    await new Promise(resolve => setTimeout(resolve, 100));
    yield i;
  }
}

const asyncIterable = generateSequence(10);
const firstFive = takeWhile(asyncIterable, x => x <= 5);

(async () => {
  for await (const value of firstFive) {
    console.log(value);
  }
})();

Bir Nechta Asinxron Iterabllarni Birlashtirish

Siz zip yoki merge kabi texnikalardan foydalanib, bir nechta asinxron iterabllarni bitta asinxron iterablega birlashtirishingiz mumkin. Bu sizga bir vaqtning o'zida bir nechta manbalardan ma'lumotlarni qayta ishlash imkonini beradi.


async function* zip(asyncIterable1, asyncIterable2) {
    const iterator1 = asyncIterable1[Symbol.asyncIterator]();
    const iterator2 = asyncIterable2[Symbol.asyncIterator]();

    while (true) {
        const result1 = await iterator1.next();
        const result2 = await iterator2.next();

        if (result1.done || result2.done) {
            break;
        }

        yield [result1.value, result2.value];
    }
}

// Foydalanish misoli:
async function* generateSequence1(end) {
    for (let i = 1; i <= end; i++) {
        yield i;
    }
}

async function* generateSequence2(end) {
    for (let i = 10; i <= end + 9; i++) {
        yield i;
    }
}

const iterable1 = generateSequence1(5);
const iterable2 = generateSequence2(5);

(async () => {
    for await (const [value1, value2] of zip(iterable1, iterable2)) {
        console.log(value1, value2);
    }
})();

Xulosa

JavaScript Asinxron Iterator Yordamchilari asinxron ma'lumotlar oqimlarini qayta ishlashning kuchli va oqlangan usulini taqdim etadi. Ular ma'lumotlarni manipulyatsiya qilish uchun funksional va kompozitsion yondashuvni taklif qilib, murakkab ma'lumotlarni qayta ishlash quvurlarini qurishni osonlashtiradi. Asinxron Iteratorlar va Asinxron Iterabllarning asosiy tushunchalarini tushunib, turli yordamchi metodlarni o'zlashtirib, siz asinxron JavaScript kodingizning samaradorligi va qo'llab-quvvatlanishini sezilarli darajada yaxshilashingiz mumkin. Brauzer va ishga tushirish muhiti qo'llab-quvvatlashi o'sishda davom etar ekan, Asinxron Iterator Yordamchilari zamonaviy JavaScript dasturchilari uchun muhim vositaga aylanishga tayyor.