Ilg'or JavaScript generator patternlarini, jumladan asinxron iteratsiya, holat mashinasi implementatsiyasi va zamonaviy veb-ishlab chiqish uchun amaliy misollarni o'rganing.
JavaScript Generatorlari: Asinxron Iteratsiya va Holat Mashinalari uchun Ilg'or Patternlar
ES6 da taqdim etilgan JavaScript generatorlari iteratsiya qilinadigan obyektlarni yaratish va murakkab boshqaruv oqimini boshqarish uchun kuchli mexanizmni taqdim etadi. Ularning asosiy qo'llanilishi nisbatan sodda bo'lsa-da, generatorlarning haqiqiy salohiyati ularning asinxron operatsiyalarni bajarish va holat mashinalarini amalga oshirish qobiliyatida yotadi. Ushbu maqolada JavaScript generatorlaridan foydalangan holda ilg'or patternlar, xususan, asinxron iteratsiya va holat mashinalarini amalga oshirish, shuningdek, zamonaviy veb-ishlab chiqish uchun tegishli amaliy misollar ko'rib chiqiladi.
JavaScript Generatorlarini Tushunish
Ilg'or patternlarga sho'ng'ishdan oldin, keling, JavaScript generatorlarining asoslarini qisqacha takrorlab o'taylik.
Generatorlar nima?
Generator - bu funksiyaning bajarilish oqimini boshqarishga imkon beruvchi, to'xtatib turilishi va qayta ishga tushirilishi mumkin bo'lgan maxsus turdagi funksiyadir. Generatorlar function*
sintaksisi yordamida aniqlanadi va ular bajarilishni to'xtatib, qiymat qaytarish uchun yield
kalit so'zidan foydalanadi.
Asosiy Tushunchalar:
function*
: Generator funksiyasini bildiradi.yield
: Funksiya bajarilishini to'xtatib turadi va qiymat qaytaradi.next()
: Funksiya bajarilishini qayta tiklaydi va ixtiyoriy ravishda generatorga qiymat qaytaradi.return()
: Generatorni tugatadi va belgilangan qiymatni qaytaradi.throw()
: Generator funksiyasi ichida xatolik yuzaga keltiradi.
Misol:
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const generator = numberGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
Generatorlar yordamida Asinxron Iteratsiya
Generatorlarning eng kuchli qo'llanilishidan biri bu asinxron operatsiyalarni, ayniqsa ma'lumotlar oqimlari bilan ishlashda, boshqarishdir. Asinxron iteratsiya sizga ma'lumotlarni paydo bo'lishi bilan qayta ishlash imkonini beradi va asosiy oqimni (main thread) bloklamaydi.
Muammo: Callback Jahannami va Promislar
JavaScriptda an'anaviy asinxron dasturlash ko'pincha callbacklar yoki promislar bilan bog'liq. Promislar callbacklarga nisbatan strukturani yaxshilasa-da, murakkab asinxron oqimlarni boshqarish hali ham qiyinlashishi mumkin.
Generatorlar, promislar yoki async/await
bilan birgalikda, asinxron iteratsiyani boshqarishning ancha toza va o'qilishi oson usulini taklif qiladi.
Asinxron Iteratorlar
Asinxron iteratorlar asinxron ma'lumotlar manbalari bo'yicha iteratsiya qilish uchun standart interfeysni taqdim etadi. Ular oddiy iteratorlarga o'xshaydi, lekin asinxron operatsiyalarni bajarish uchun promislardan foydalanadi.
Asinxron iteratorlar value
va done
xususiyatlariga ega obyekt bilan hal qilinadigan promisni qaytaruvchi next()
metodiga ega.
Misol:
async function* asyncNumberGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}
async function consumeGenerator() {
const generator = asyncNumberGenerator();
console.log(await generator.next()); // { value: 1, done: false }
console.log(await generator.next()); // { value: 2, done: false }
console.log(await generator.next()); // { value: 3, done: false }
console.log(await generator.next()); // { value: undefined, done: true }
}
consumeGenerator();
Asinxron Iteratsiya uchun Haqiqiy Hayotdagi Qo'llash Holatlari
- APIdan ma'lumotlarni oqim (streaming) orqali olish: Sahifalash (pagination) yordamida serverdan ma'lumotlarni qismlarga bo'lib olish. Foydalanuvchi brauzerini ortiqcha yuklamaslik uchun postlarni partiyalarga bo'lib olmoqchi bo'lgan ijtimoiy media platformasini tasavvur qiling.
- Katta fayllarni qayta ishlash: Katta fayllarni butunlay xotiraga yuklamasdan qatorma-qator o'qish va qayta ishlash. Bu ma'lumotlar tahlili ssenariylarida juda muhim.
- Haqiqiy vaqtdagi ma'lumotlar oqimlari: WebSocket yoki Server-Sent Events (SSE) oqimidan real vaqtdagi ma'lumotlarni qayta ishlash. Jonli sport natijalari ilovasini o'ylab ko'ring.
Misol: APIdan ma'lumotlarni oqim orqali olish
Keling, sahifalashdan foydalanadigan APIdan ma'lumotlarni olish misolini ko'rib chiqaylik. Biz barcha ma'lumotlar olinmaguncha ma'lumotlarni qismlarga bo'lib oladigan generator yaratamiz.
async function* paginatedDataFetcher(url, pageSize = 10) {
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(`${url}?page=${page}&pageSize=${pageSize}`);
const data = await response.json();
if (data.length === 0) {
hasMore = false;
return;
}
for (const item of data) {
yield item;
}
page++;
}
}
async function consumeData() {
const dataStream = paginatedDataFetcher('https://api.example.com/data');
for await (const item of dataStream) {
console.log(item);
// Har bir element kelganda uni qayta ishlash
}
console.log('Ma\'lumotlar oqimi yakunlandi.');
}
consumeData();
Ushbu misolda:
paginatedDataFetcher
- bu sahifalash yordamida APIdan ma'lumotlarni oladigan asinxron generator.yield item
iborasi bajarilishni to'xtatadi va har bir ma'lumot elementini qaytaradi.consumeData
funksiyasi ma'lumotlar oqimi bo'ylab asinxron ravishda iteratsiya qilish uchunfor await...of
siklidan foydalanadi.
Ushbu yondashuv ma'lumotlarni paydo bo'lishi bilan qayta ishlashga imkon beradi, bu esa katta hajmdagi ma'lumotlar to'plamlari bilan ishlashni samarali qiladi.
Generatorlar yordamida Holat Mashinalari
Generatorlarning yana bir kuchli qo'llanilishi holat mashinalarini amalga oshirishdir. Holat mashinasi - bu kiruvchi hodisalarga asoslanib turli holatlar o'rtasida o'tadigan hisoblash modelidir.
Holat Mashinalari nima?
Holat mashinalari cheklangan miqdordagi holatlarga va ushbu holatlar o'rtasidagi o'tishlarga ega bo'lgan tizimlarni modellashtirish uchun ishlatiladi. Ular dasturiy injiniringda murakkab tizimlarni loyihalash uchun keng qo'llaniladi.
Holat mashinasining asosiy komponentlari:
- Holatlar: Tizimning turli shartlari yoki rejimlarini ifodalaydi.
- Hodisalar: Holatlar o'rtasidagi o'tishlarni ishga tushiradi.
- O'tishlar: Hodisalarga asoslanib bir holatdan ikkinchisiga o'tish qoidalarini belgilaydi.
Generatorlar yordamida Holat Mashinalarini Amalga Oshirish
Generatorlar holat mashinalarini amalga oshirishning tabiiy usulini taqdim etadi, chunki ular ichki holatni saqlab turishi va kiruvchi hodisalarga asoslanib bajarilish oqimini boshqarishi mumkin.
Generatordagi har bir yield
iborasi holatni ifodalashi mumkin va next()
metodi holatlar o'rtasidagi o'tishlarni ishga tushirish uchun ishlatilishi mumkin.
Misol: Oddiy Svetofor Holat Mashinasi
Keling, uchta holatga ega bo'lgan oddiy svetofor holat mashinasini ko'rib chiqaylik: QIZIL
, SARIQ
, va YASHIL
.
function* trafficLightStateMachine() {
let state = 'RED';
while (true) {
switch (state) {
case 'RED':
console.log('Svetofor: QIZIL');
state = yield;
break;
case 'YELLOW':
console.log('Svetofor: SARIQ');
state = yield;
break;
case 'GREEN':
console.log('Svetofor: YASHIL');
state = yield;
break;
default:
console.log('Yaroqsiz Holat');
state = yield;
}
}
}
const trafficLight = trafficLightStateMachine();
trafficLight.next(); // Boshlang'ich holat: QIZIL
trafficLight.next('GREEN'); // YASHIL ga o'tish
trafficLight.next('YELLOW'); // SARIQ ga o'tish
trafficLight.next('RED'); // QIZIL ga o'tish
Ushbu misolda:
trafficLightStateMachine
- bu svetofor holat mashinasini ifodalovchi generator.state
o'zgaruvchisi svetoforning joriy holatini saqlaydi.yield
iborasi bajarilishni to'xtatadi va keyingi holatga o'tishni kutadi.next()
metodi holatlar o'rtasidagi o'tishlarni ishga tushirish uchun ishlatiladi.
Ilg'or Holat Mashinasi Patternlari
1. Holat Ta'riflari uchun Obyektlardan Foydalanish
Holat mashinasini qo'llab-quvvatlashni osonlashtirish uchun holatlarni bog'liq amallarga ega obyektlar sifatida aniqlash mumkin.
const states = {
RED: {
name: 'RED',
action: () => console.log('Svetofor: QIZIL'),
},
YELLOW: {
name: 'YELLOW',
action: () => console.log('Svetofor: SARIQ'),
},
GREEN: {
name: 'GREEN',
action: () => console.log('Svetofor: YASHIL'),
},
};
function* trafficLightStateMachine() {
let currentState = states.RED;
while (true) {
currentState.action();
const nextStateName = yield;
currentState = states[nextStateName] || currentState; // Agar yaroqsiz bo'lsa, joriy holatga qaytish
}
}
const trafficLight = trafficLightStateMachine();
trafficLight.next(); // Boshlang'ich holat: QIZIL
trafficLight.next('GREEN'); // YASHIL ga o'tish
trafficLight.next('YELLOW'); // SARIQ ga o'tish
trafficLight.next('RED'); // QIZIL ga o'tish
2. Hodisalarni O'tishlar bilan Boshqarish
Siz hodisalarga asoslanib holatlar o'rtasida aniq o'tishlarni belgilashingiz mumkin.
const states = {
RED: {
name: 'RED',
action: () => console.log('Svetofor: QIZIL'),
transitions: {
TIMER: 'GREEN',
},
},
YELLOW: {
name: 'YELLOW',
action: () => console.log('Svetofor: SARIQ'),
transitions: {
TIMER: 'RED',
},
},
GREEN: {
name: 'GREEN',
action: () => console.log('Svetofor: YASHIL'),
transitions: {
TIMER: 'YELLOW',
},
},
};
function* trafficLightStateMachine() {
let currentState = states.RED;
while (true) {
currentState.action();
const event = yield;
const nextStateName = currentState.transitions[event];
currentState = states[nextStateName] || currentState; // Agar yaroqsiz bo'lsa, joriy holatga qaytish
}
}
const trafficLight = trafficLightStateMachine();
trafficLight.next(); // Boshlang'ich holat: QIZIL
// Bir muncha vaqt o'tgach, taymer hodisasini simulyatsiya qilish
setTimeout(() => {
trafficLight.next('TIMER'); // YASHIL ga o'tish
setTimeout(() => {
trafficLight.next('TIMER'); // SARIQ ga o'tish
setTimeout(() => {
trafficLight.next('TIMER'); // QIZIL ga o'tish
}, 2000);
}, 5000);
}, 5000);
Holat Mashinalari uchun Haqiqiy Hayotdagi Qo'llash Holatlari
- UI Komponenti Holatini Boshqarish: UI komponentining holatini, masalan, tugma (
IDLE
(bo'sh),HOVER
(ustiga olib borilgan),PRESSED
(bosilgan),DISABLED
(o'chirilgan)) holatini boshqarish. - Ish Jarayonlarini Boshqarish: Murakkab ish jarayonlarini, masalan, buyurtmani qayta ishlash yoki hujjatni tasdiqlashni amalga oshirish.
- O'yin Yaratish: O'yin obyektlarining xatti-harakatlarini (masalan,
IDLE
(bo'sh),WALKING
(yurish),ATTACKING
(hujum qilish),DEAD
(o'lgan)) boshqarish.
Generatorlarda Xatolarni Qayta Ishlash
Generatorlar bilan ishlashda, ayniqsa asinxron operatsiyalar yoki holat mashinalari bilan ishlaganda, xatolarni qayta ishlash juda muhim. Generatorlar try...catch
bloki va throw()
metodi yordamida xatolarni qayta ishlash mexanizmlarini taqdim etadi.
try...catch
dan foydalanish
Bajarilish paytida yuzaga keladigan xatolarni ushlash uchun generator funksiyasi ichida try...catch
blokidan foydalanishingiz mumkin.
function* errorGenerator() {
try {
yield 1;
throw new Error('Nimadir noto\'g\'ri ketdi');
yield 2; // Bu qator bajarilmaydi
} catch (error) {
console.error('Xato ushlandi:', error.message);
yield 'Xato qayta ishlandi';
}
yield 3;
}
const generator = errorGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // Xato ushlandi: Nimadir noto'g'ri ketdi
// { value: 'Xato qayta ishlandi', done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
throw()
dan foydalanish
throw()
metodi sizga generatorga tashqaridan xatolik yuborish imkonini beradi.
function* throwGenerator() {
try {
yield 1;
yield 2;
} catch (error) {
console.error('Xato ushlandi:', error.message);
yield 'Xato qayta ishlandi';
}
yield 3;
}
const generator = throwGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.throw(new Error('Tashqi xato'))); // Xato ushlandi: Tashqi xato
// { value: 'Xato qayta ishlandi', done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
Asinxron Iteratorlarda Xatolarni Qayta Ishlash
Asinxron iteratorlar bilan ishlaganda, asinxron operatsiyalar davomida yuzaga kelishi mumkin bo'lgan xatolarni qayta ishlashingiz kerak.
async function* asyncErrorGenerator() {
try {
yield await Promise.reject(new Error('Asinxron xato'));
} catch (error) {
console.error('Asinxron xato ushlandi:', error.message);
yield 'Asinxron xato qayta ishlandi';
}
}
async function consumeGenerator() {
const generator = asyncErrorGenerator();
console.log(await generator.next()); // Asinxron xato ushlandi: Asinxron xato
// { value: 'Asinxron xato qayta ishlandi', done: false }
}
consumeGenerator();
Generatorlardan Foydalanish bo'yicha Eng Yaxshi Amaliyotlar
- Murakkab boshqaruv oqimlari uchun generatorlardan foydalaning: Generatorlar funksiyaning bajarilish oqimi ustidan nozik nazoratga muhtoj bo'lgan ssenariylar uchun eng mos keladi.
- Asinxron operatsiyalar uchun generatorlarni promislar yoki
async/await
bilan birlashtiring: Bu asinxron kodni yanada sinxron va o'qilishi oson uslubda yozish imkonini beradi. - Murakkab holatlar va o'tishlarni boshqarish uchun holat mashinalaridan foydalaning: Holat mashinalari murakkab tizimlarni tuzilgan va qo'llab-quvvatlanadigan tarzda modellashtirish va amalga oshirishga yordam beradi.
- Xatolarni to'g'ri qayta ishlang: Kutilmagan xatti-harakatlarning oldini olish uchun har doim generatorlaringiz ichida xatolarni qayta ishlang.
- Generatorlarni kichik va maqsadli qilib saqlang: Har bir generator aniq va belgilangan maqsadga ega bo'lishi kerak.
- Generatorlaringizni hujjatlashtiring: Generatorlaringiz uchun, ularning maqsadi, kirish va chiqish ma'lumotlarini o'z ichiga olgan aniq hujjatlarni taqdim eting. Bu kodni tushunish va qo'llab-quvvatlashni osonlashtiradi.
Xulosa
JavaScript generatorlari asinxron operatsiyalarni boshqarish va holat mashinalarini amalga oshirish uchun kuchli vositadir. Asinxron iteratsiya va holat mashinasini amalga oshirish kabi ilg'or patternlarni tushunish orqali siz yanada samarali, qo'llab-quvvatlanadigan va o'qilishi oson kod yozishingiz mumkin. APIdan ma'lumotlarni oqim orqali olayotgan bo'lsangiz, UI komponentlari holatlarini boshqarayotgan bo'lsangiz yoki murakkab ish jarayonlarini amalga oshirayotgan bo'lsangiz ham, generatorlar keng ko'lamdagi dasturlash muammolari uchun moslashuvchan va nafis yechimni taqdim etadi. JavaScript ishlab chiqish mahoratingizni oshirish va yanada mustahkam va kengaytiriladigan ilovalarni yaratish uchun generatorlarning kuchini qabul qiling.