Objavte pomocníkov pre asynchrónne iterátory v JavaScripte, ktoré prinášajú revolúciu do spracovania streamov. Naučte sa efektívne narábať s asynchrónnymi dátovými streamami pomocou map, filter, take, drop a ďalších.
Pomocníci pre asynchrónne iterátory v JavaScripte: Výkonné spracovanie streamov pre moderné aplikácie
V modernom vývoji JavaScriptu je práca s asynchrónnymi dátovými streamami bežnou požiadavkou. Či už načítavate dáta z API, spracovávate veľké súbory alebo riešite udalosti v reálnom čase, efektívne spravovanie asynchrónnych dát je kľúčové. Pomocníci pre asynchrónne iterátory v JavaScripte poskytujú výkonný a elegantný spôsob spracovania týchto streamov, ponúkajúc funkcionálny a skladateľný prístup k manipulácii s dátami.
Čo sú asynchrónne iterátory a asynchrónne iterovateľné objekty?
Predtým, ako sa ponoríme do pomocníkov pre asynchrónne iterátory, poďme si vysvetliť základné pojmy: asynchrónne iterátory a asynchrónne iterovateľné objekty.
Asynchrónny iterovateľný objekt (Async Iterable) je objekt, ktorý definuje spôsob asynchrónneho iterovania cez svoje hodnoty. Robí to implementáciou metódy @@asyncIterator
, ktorá vracia asynchrónny iterátor.
Asynchrónny iterátor (Async Iterator) je objekt, ktorý poskytuje metódu next()
. Táto metóda vracia promise, ktorá sa resolvne na objekt s dvoma vlastnosťami:
value
: Nasledujúca hodnota v sekvencii.done
: Booleovská hodnota, ktorá udáva, či bola sekvencia úplne spracovaná.
Tu je jednoduchý príklad:
async function* generateSequence(end) {
for (let i = 1; i <= end; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Simulácia asynchrónnej operácie
yield i;
}
}
const asyncIterable = generateSequence(5);
(async () => {
for await (const value of asyncIterable) {
console.log(value); // Výstup: 1, 2, 3, 4, 5 (s oneskorením 500ms medzi každým)
}
})();
V tomto príklade je generateSequence
asynchrónna generátorová funkcia, ktorá produkuje sekvenciu čísel asynchrónne. Cyklus for await...of
sa používa na spracovanie hodnôt z asynchrónneho iterovateľného objektu.
Predstavenie pomocníkov pre asynchrónne iterátory
Pomocníci pre asynchrónne iterátory rozširujú funkcionalitu asynchrónnych iterátorov a poskytujú súbor metód na transformáciu, filtrovanie a manipuláciu s asynchrónnymi dátovými streamami. Umožňujú funkcionálny a skladateľný štýl programovania, čo uľahčuje budovanie zložitých dátových spracovateľských kanálov.
Medzi hlavných pomocníkov pre asynchrónne iterátory patria:
map()
: Transformuje každý prvok streamu.filter()
: Vyberá prvky zo streamu na základe podmienky.take()
: Vráti prvých N prvkov streamu.drop()
: Preskočí prvých N prvkov streamu.toArray()
: Zozbiera všetky prvky streamu do poľa.forEach()
: Vykoná poskytnutú funkciu raz pre každý prvok streamu.some()
: Skontroluje, či aspoň jeden prvok spĺňa zadanú podmienku.every()
: Skontroluje, či všetky prvky spĺňajú zadanú podmienku.find()
: Vráti prvý prvok, ktorý spĺňa zadanú podmienku.reduce()
: Aplikuje funkciu na akumulátor a každý prvok, aby ich zredukovala na jednu hodnotu.
Pozrime sa na každého pomocníka s príkladmi.
map()
Pomocník map()
transformuje každý prvok asynchrónneho iterovateľného objektu pomocou poskytnutej funkcie. Vracia nový asynchrónny iterovateľný objekt s transformovanými hodnotami.
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); // Výstup: 2, 4, 6, 8, 10 (s oneskorením 100ms)
}
})();
V tomto príklade map(x => x * 2)
zdvojnásobí každé číslo v sekvencii.
filter()
Pomocník filter()
vyberá prvky z asynchrónneho iterovateľného objektu na základe poskytnutej podmienky (predikátovej funkcie). Vracia nový asynchrónny iterovateľný objekt obsahujúci iba prvky, ktoré spĺňajú podmienku.
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); // Výstup: 2, 4, 6, 8, 10 (s oneskorením 100ms)
}
})();
V tomto príklade filter(x => x % 2 === 0)
vyberie zo sekvencie iba párne čísla.
take()
Pomocník take()
vráti prvých N prvkov z asynchrónneho iterovateľného objektu. Vracia nový asynchrónny iterovateľný objekt obsahujúci iba zadaný počet prvkov.
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); // Výstup: 1, 2, 3 (s oneskorením 100ms)
}
})();
V tomto príklade take(3)
vyberie prvé tri čísla zo sekvencie.
drop()
Pomocník drop()
preskočí prvých N prvkov z asynchrónneho iterovateľného objektu a vráti zvyšok. Vracia nový asynchrónny iterovateľný objekt obsahujúci zostávajúce prvky.
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); // Výstup: 3, 4, 5 (s oneskorením 100ms)
}
})();
V tomto príklade drop(2)
preskočí prvé dve čísla zo sekvencie.
toArray()
Pomocník toArray()
spracuje celý asynchrónny iterovateľný objekt a zozbiera všetky prvky do poľa. Vracia promise, ktorá sa resolvne na pole obsahujúce všetky prvky.
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); // Výstup: [1, 2, 3, 4, 5]
})();
V tomto príklade toArray()
zozbiera všetky čísla zo sekvencie do poľa.
forEach()
Pomocník forEach()
vykoná poskytnutú funkciu raz pre každý prvok v asynchrónnom iterovateľnom objekte. *Nevracia* nový asynchrónny iterovateľný objekt, vykonáva funkciu s vedľajšími účinkami. To môže byť užitočné pre operácie ako logovanie alebo aktualizácia používateľského rozhrania.
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("Value:", value);
});
console.log("forEach completed");
})();
// Výstup: Value: 1, Value: 2, Value: 3, forEach completed
some()
Pomocník some()
testuje, či aspoň jeden prvok v asynchrónnom iterovateľnom objekte prejde testom implementovaným poskytnutou funkciou. Vracia promise, ktorá sa resolvne na booleovskú hodnotu (true
, ak aspoň jeden prvok spĺňa podmienku, inak false
).
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("Has even number:", hasEvenNumber); // Výstup: Has even number: true
})();
every()
Pomocník every()
testuje, či všetky prvky v asynchrónnom iterovateľnom objekte prejdú testom implementovaným poskytnutou funkciou. Vracia promise, ktorá sa resolvne na booleovskú hodnotu (true
, ak všetky prvky spĺňajú podmienku, inak false
).
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("Are all even:", areAllEven); // Výstup: Are all even: true
})();
find()
Pomocník find()
vráti prvý prvok v asynchrónnom iterovateľnom objekte, ktorý spĺňa poskytnutú testovaciu funkciu. Ak žiadna hodnota nespĺňa testovaciu funkciu, vráti sa undefined
. Vracia promise, ktorá sa resolvne na nájdený prvok alebo undefined
.
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("First even number:", firstEven); // Výstup: First even number: 2
})();
reduce()
Pomocník reduce()
vykoná používateľom zadanú spätnú „reducer“ funkciu na každom prvku asynchrónneho iterovateľného objektu v poradí, pričom odovzdáva návratovú hodnotu z výpočtu na predchádzajúcom prvku. Konečným výsledkom spustenia reducera na všetkých prvkoch je jedna hodnota. Vracia promise, ktorá sa resolvne na konečnú akumulovanú hodnotu.
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("Sum:", sum); // Výstup: Sum: 15
})();
Praktické príklady a prípady použitia
Pomocníci pre asynchrónne iterátory sú cenní v rôznych scenároch. Pozrime sa na niekoľko praktických príkladov:
1. Spracovanie dát zo streamovacieho API
Predstavte si, že budujete vizualizačný panel s dátami v reálnom čase, ktorý prijíma dáta zo streamovacieho API. API posiela aktualizácie nepretržite a vy potrebujete tieto aktualizácie spracovať, aby ste zobrazili najnovšie informácie.
async function* fetchDataFromAPI(url) {
let response = await fetch(url);
if (!response.body) {
throw new Error("ReadableStream not supported in this environment");
}
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);
// Predpokladáme, že API posiela JSON objekty oddelené novými riadkami
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'; // Nahraďte URL vášho API
const dataStream = fetchDataFromAPI(apiURL);
// Spracovanie dátového streamu
(async () => {
for await (const data of dataStream.filter(item => item.type === 'metric').map(item => ({ timestamp: item.timestamp, value: item.value }))) {
console.log('Processed Data:', data);
// Aktualizácia panelu so spracovanými dátami
}
})();
V tomto príklade fetchDataFromAPI
načítava dáta zo streamovacieho API, parsuje JSON objekty a poskytuje ich ako asynchrónny iterovateľný objekt. Pomocník filter
vyberá iba metriky a pomocník map
transformuje dáta do požadovaného formátu pred aktualizáciou panelu.
2. Čítanie a spracovanie veľkých súborov
Predpokladajme, že potrebujete spracovať veľký CSV súbor obsahujúci údaje o zákazníkoch. Namiesto načítania celého súboru do pamäte môžete použiť pomocníkov pre asynchrónne iterátory na jeho spracovanie po častiach (chunk by chunk).
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'; // Nahraďte cestou k vášmu súboru
const lines = readLinesFromFile(filePath);
// Spracovanie riadkov
(async () => {
for await (const customerData of lines.drop(1).map(line => line.split(',')).filter(data => data[2] === 'USA')) {
console.log('Customer from USA:', customerData);
// Spracovanie údajov o zákazníkoch z USA
}
})();
V tomto príklade readLinesFromFile
číta súbor riadok po riadku a poskytuje každý riadok ako asynchrónny iterovateľný objekt. Pomocník drop(1)
preskočí hlavičkový riadok, pomocník map
rozdelí riadok na stĺpce a pomocník filter
vyberie iba zákazníkov z USA.
3. Spracovanie udalostí v reálnom čase
Pomocníci pre asynchrónne iterátory môžu byť tiež použití na spracovanie udalostí v reálnom čase zo zdrojov ako sú WebSockets. Môžete vytvoriť asynchrónny iterovateľný objekt, ktorý emituje udalosti, ako prichádzajú, a potom použiť pomocníkov na spracovanie týchto udalostí.
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); // Resolvne s null, keď sa spojenie uzavrie
}
});
}
} finally {
ws.close();
}
}
const websocketURL = 'wss://example.com/events'; // Nahraďte URL vášho WebSocketu
const eventStream = createWebSocketStream(websocketURL);
// Spracovanie streamu udalostí
(async () => {
for await (const event of eventStream.filter(event => event.type === 'user_login').map(event => ({ userId: event.userId, timestamp: event.timestamp }))) {
console.log('User Login Event:', event);
// Spracovanie udalosti prihlásenia používateľa
}
})();
V tomto príklade createWebSocketStream
vytvára asynchrónny iterovateľný objekt, ktorý emituje udalosti prijaté z WebSocketu. Pomocník filter
vyberá iba udalosti prihlásenia používateľa a pomocník map
transformuje dáta do požadovaného formátu.
Výhody používania pomocníkov pre asynchrónne iterátory
- Zlepšená čitateľnosť a udržiavateľnosť kódu: Pomocníci pre asynchrónne iterátory podporujú funkcionálny a skladateľný štýl programovania, vďaka čomu je váš kód ľahšie čitateľný, zrozumiteľný a udržiavateľný. Zreťazená povaha pomocníkov vám umožňuje vyjadriť zložité dátové spracovateľské kanály stručným a deklaratívnym spôsobom.
- Efektívne využitie pamäte: Pomocníci pre asynchrónne iterátory spracovávajú dátové streamy lenivo (lazily), čo znamená, že spracovávajú dáta iba podľa potreby. To môže výrazne znížiť využitie pamäte, najmä pri práci s veľkými dátovými sadami alebo nepretržitými dátovými streamami.
- Zvýšený výkon: Spracovaním dát v streame môžu pomocníci pre asynchrónne iterátory zlepšiť výkon tým, že sa vyhnú potrebe načítať celú dátovú sadu do pamäte naraz. To môže byť obzvlášť prospešné pre aplikácie, ktoré pracujú s veľkými súbormi, dátami v reálnom čase alebo streamovacími API.
- Zjednodušené asynchrónne programovanie: Pomocníci pre asynchrónne iterátory abstrahujú zložitosť asynchrónneho programovania, čo uľahčuje prácu s asynchrónnymi dátovými streamami. Nemusíte manuálne spravovať promises alebo spätné volania (callbacks); pomocníci sa postarajú o asynchrónne operácie na pozadí.
- Skladateľný a znovupoužiteľný kód: Pomocníci pre asynchrónne iterátory sú navrhnutí tak, aby boli skladateľní, čo znamená, že ich môžete ľahko zreťaziť a vytvárať tak zložité dátové spracovateľské kanály. To podporuje znovupoužiteľnosť kódu a znižuje jeho duplicitu.
Podpora v prehliadačoch a runtime prostrediach
Pomocníci pre asynchrónne iterátory sú v JavaScripte stále relatívne novou funkciou. Koncom roka 2024 sú v 3. fáze štandardizačného procesu TC39, čo znamená, že je pravdepodobné, že budú v blízkej budúcnosti štandardizované. Zatiaľ však nie sú natívne podporované vo všetkých prehliadačoch a verziách Node.js.
Podpora v prehliadačoch: Moderné prehliadače ako Chrome, Firefox, Safari a Edge postupne pridávajú podporu pre pomocníkov pre asynchrónne iterátory. Najnovšie informácie o kompatibilite prehliadačov si môžete overiť na webových stránkach ako Can I use..., aby ste zistili, ktoré prehliadače túto funkciu podporujú.
Podpora v Node.js: Novšie verzie Node.js (v18 a vyššie) poskytujú experimentálnu podporu pre pomocníkov pre asynchrónne iterátory. Na ich použitie možno budete musieť spustiť Node.js s príznakom --experimental-async-iterator
.
Polyfilly: Ak potrebujete použiť pomocníkov pre asynchrónne iterátory v prostrediach, ktoré ich natívne nepodporujú, môžete použiť polyfill. Polyfill je kus kódu, ktorý poskytuje chýbajúcu funkcionalitu. K dispozícii je niekoľko polyfill knižníc pre pomocníkov pre asynchrónne iterátory; populárnou možnosťou je knižnica core-js
.
Implementácia vlastných asynchrónnych iterátorov
Hoci pomocníci pre asynchrónne iterátory poskytujú pohodlný spôsob spracovania existujúcich asynchrónnych iterovateľných objektov, niekedy možno budete potrebovať vytvoriť si vlastné. To vám umožní spracovávať dáta z rôznych zdrojov, ako sú databázy, API alebo súborové systémy, streamovacím spôsobom.
Na vytvorenie vlastného asynchrónneho iterátora musíte na objekte implementovať metódu @@asyncIterator
. Táto metóda by mala vrátiť objekt s metódou next()
. Metóda next()
by mala vrátiť promise, ktorá sa resolvne na objekt s vlastnosťami value
a done
.
Tu je príklad vlastného asynchrónneho iterátora, ktorý načítava dáta zo stránkovaného API:
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'; // Nahraďte URL vášho API
const paginatedData = fetchPaginatedData(apiBaseURL);
// Spracovanie stránkovaných dát
(async () => {
for await (const item of paginatedData) {
console.log('Item:', item);
// Spracovanie položky
}
})();
V tomto príklade fetchPaginatedData
načítava dáta zo stránkovaného API a poskytuje každú položku, ako je získaná. Asynchrónny iterátor sa stará o logiku stránkovania, čo uľahčuje spracovanie dát streamovacím spôsobom.
Potenciálne výzvy a úvahy
Hoci pomocníci pre asynchrónne iterátory ponúkajú množstvo výhod, je dôležité si byť vedomý niektorých potenciálnych výziev a úvah:
- Spracovanie chýb: Správne spracovanie chýb je kľúčové pri práci s asynchrónnymi dátovými streamami. Musíte zvládnuť potenciálne chyby, ktoré môžu nastať počas načítavania, spracovania alebo transformácie dát. Používanie blokov
try...catch
a techník na spracovanie chýb v rámci vašich pomocníkov pre asynchrónne iterátory je nevyhnutné. - Zrušenie: V niektorých scenároch možno budete potrebovať zrušiť spracovanie asynchrónneho iterovateľného objektu predtým, ako je úplne spracovaný. To môže byť užitočné pri dlhotrvajúcich operáciách alebo dátových streamoch v reálnom čase, kde chcete zastaviť spracovanie po splnení určitej podmienky. Implementácia mechanizmov na zrušenie, ako je použitie
AbortController
, vám môže pomôcť efektívne spravovať asynchrónne operácie. - Spätný tlak (Backpressure): Pri práci s dátovými streamami, ktoré produkujú dáta rýchlejšie, ako sa dajú spotrebovať, sa stáva problémom spätný tlak. Spätný tlak sa vzťahuje na schopnosť spotrebiteľa signalizovať producentovi, aby spomalil rýchlosť, akou sú dáta emitované. Implementácia mechanizmov spätného tlaku môže zabrániť preťaženiu pamäte a zabezpečiť, že dátový stream je spracovaný efektívne.
- Ladenie (Debugging): Ladenie asynchrónneho kódu môže byť náročnejšie ako ladenie synchrónneho kódu. Pri práci s pomocníkmi pre asynchrónne iterátory je dôležité používať ladiace nástroje a techniky na sledovanie toku dát cez kanál a identifikáciu akýchkoľvek potenciálnych problémov.
Osvedčené postupy pre používanie pomocníkov pre asynchrónne iterátory
Aby ste z pomocníkov pre asynchrónne iterátory vyťažili čo najviac, zvážte nasledujúce osvedčené postupy:
- Používajte popisné názvy premenných: Vyberajte popisné názvy premenných, ktoré jasne naznačujú účel každého asynchrónneho iterovateľného objektu a pomocníka. Váš kód bude tak ľahšie čitateľný a zrozumiteľný.
- Udržujte pomocné funkcie stručné: Udržujte funkcie odovzdávané pomocníkom pre asynchrónne iterátory čo najstručnejšie a najzameranejšie. Vyhnite sa vykonávaniu zložitých operácií v rámci týchto funkcií; namiesto toho vytvorte samostatné funkcie pre zložitú logiku.
- Zreťazujte pomocníkov pre lepšiu čitateľnosť: Zreťazujte pomocníkov pre asynchrónne iterátory, aby ste vytvorili jasný a deklaratívny dátový spracovateľský kanál. Vyhnite sa nadmernému vnárania pomocníkov, pretože to môže sťažiť čitateľnosť vášho kódu.
- Spracovávajte chyby elegantne: Implementujte správne mechanizmy na spracovanie chýb, aby ste zachytili a zvládli potenciálne chyby, ktoré môžu nastať počas spracovania dát. Poskytnite informatívne chybové hlásenia, ktoré pomôžu pri diagnostike a riešení problémov.
- Dôkladne testujte svoj kód: Dôkladne testujte svoj kód, aby ste sa uistili, že správne zvláda rôzne scenáre. Píšte jednotkové testy (unit tests) na overenie správania jednotlivých pomocníkov a integračné testy na overenie celkového dátového spracovateľského kanála.
Pokročilé techniky
Skladanie vlastných pomocníkov
Môžete si vytvoriť vlastných pomocníkov pre asynchrónne iterátory skladaním existujúcich pomocníkov alebo ich budovaním od nuly. To vám umožní prispôsobiť funkcionalitu vašim špecifickým potrebám a vytvárať znovupoužiteľné komponenty.
async function* takeWhile(asyncIterable, predicate) {
for await (const value of asyncIterable) {
if (!predicate(value)) {
break;
}
yield value;
}
}
// Príklad použitia:
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);
}
})();
Kombinovanie viacerých asynchrónnych iterovateľných objektov
Môžete skombinovať viacero asynchrónnych iterovateľných objektov do jedného pomocou techník ako zip
alebo merge
. To vám umožní spracovávať dáta z viacerých zdrojov súčasne.
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];
}
}
// Príklad použitia:
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);
}
})();
Záver
Pomocníci pre asynchrónne iterátory v JavaScripte poskytujú výkonný a elegantný spôsob spracovania asynchrónnych dátových streamov. Ponúkajú funkcionálny a skladateľný prístup k manipulácii s dátami, čo uľahčuje budovanie zložitých dátových spracovateľských kanálov. Porozumením základným konceptom asynchrónnych iterátorov a asynchrónnych iterovateľných objektov a zvládnutím rôznych pomocných metód môžete výrazne zlepšiť efektivitu a udržiavateľnosť vášho asynchrónneho JavaScript kódu. S rastúcou podporou v prehliadačoch a runtime prostrediach sú pomocníci pre asynchrónne iterátory pripravení stať sa nevyhnutným nástrojom pre moderných vývojárov JavaScriptu.