Istražite JavaScript Async Iterator Helpers za revolucionarnu obradu tokova. Naučite kako učinkovito rukovati asinkronim tokovima podataka pomoću map, filter, take, drop i drugih.
JavaScript Async Iterator Helpers: Moćna obrada tokova za moderne aplikacije
U modernom JavaScript razvoju, rad s asinkronim tokovima podataka čest je zahtjev. Bilo da dohvaćate podatke s API-ja, obrađujete velike datoteke ili rukujete događajima u stvarnom vremenu, učinkovito upravljanje asinkronim podacima je ključno. JavaScriptovi Async Iterator Helpers pružaju moćan i elegantan način za obradu tih tokova, nudeći funkcionalan i kompozabilan pristup manipulaciji podacima.
Što su asinkroni iteratori i asinkroni iterabili?
Prije nego što zaronimo u Async Iterator Helpers, razumijmo temeljne koncepte: asinkrone iteratore i asinkrone iterabile.
Asinkroni iterabil je objekt koji definira način asinkronog iteriranja preko svojih vrijednosti. To čini implementacijom metode @@asyncIterator
, koja vraća asinkroni iterator.
Asinkroni iterator je objekt koji pruža metodu next()
. Ova metoda vraća promise koji se rješava u objekt s dva svojstva:
value
: Sljedeća vrijednost u nizu.done
: Booleova vrijednost koja označava je li niz u potpunosti konzumiran.
Evo jednostavnog primjera:
async function* generateSequence(end) {
for (let i = 1; i <= end; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Simulacija asinkrone operacije
yield i;
}
}
const asyncIterable = generateSequence(5);
(async () => {
for await (const value of asyncIterable) {
console.log(value); // Izlaz: 1, 2, 3, 4, 5 (s kašnjenjem od 500ms između svakog)
}
})();
U ovom primjeru, generateSequence
je asinkrona generatorska funkcija koja asinkrono proizvodi niz brojeva. Petlja for await...of
koristi se za konzumiranje vrijednosti iz asinkronog iterabila.
Uvod u Async Iterator Helpers
Async Iterator Helpers proširuju funkcionalnost asinkronih iteratora, pružajući skup metoda za transformaciju, filtriranje i manipulaciju asinkronim tokovima podataka. Omogućuju funkcionalan i kompozabilan stil programiranja, olakšavajući izgradnju složenih cjevovoda za obradu podataka.
Osnovni Async Iterator Helpers uključuju:
map()
: Transformira svaki element toka.filter()
: Odabire elemente iz toka na temelju uvjeta.take()
: Vraća prvih N elemenata toka.drop()
: Preskače prvih N elemenata toka.toArray()
: Skuplja sve elemente toka u polje.forEach()
: Izvršava zadanu funkciju jednom za svaki element toka.some()
: Provjerava zadovoljava li barem jedan element zadani uvjet.every()
: Provjerava zadovoljavaju li svi elementi zadani uvjet.find()
: Vraća prvi element koji zadovoljava zadani uvjet.reduce()
: Primjenjuje funkciju na akumulator i svaki element kako bi ga sveo na jednu vrijednost.
Istražimo svaki pomoćnik s primjerima.
map()
Pomoćnik map()
transformira svaki element asinkronog iterabila pomoću zadane funkcije. Vraća novi asinkroni iterabil s transformiranim vrijednostima.
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); // Izlaz: 2, 4, 6, 8, 10 (s kašnjenjem od 100ms)
}
})();
U ovom primjeru, map(x => x * 2)
udvostručuje svaki broj u nizu.
filter()
Pomoćnik filter()
odabire elemente iz asinkronog iterabila na temelju zadanog uvjeta (predikatne funkcije). Vraća novi asinkroni iterabil koji sadrži samo elemente koji zadovoljavaju uvjet.
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); // Izlaz: 2, 4, 6, 8, 10 (s kašnjenjem od 100ms)
}
})();
U ovom primjeru, filter(x => x % 2 === 0)
odabire samo parne brojeve iz niza.
take()
Pomoćnik take()
vraća prvih N elemenata iz asinkronog iterabila. Vraća novi asinkroni iterabil koji sadrži samo navedeni broj elemenata.
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); // Izlaz: 1, 2, 3 (s kašnjenjem od 100ms)
}
})();
U ovom primjeru, take(3)
odabire prva tri broja iz niza.
drop()
Pomoćnik drop()
preskače prvih N elemenata iz asinkronog iterabila i vraća ostatak. Vraća novi asinkroni iterabil koji sadrži preostale elemente.
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); // Izlaz: 3, 4, 5 (s kašnjenjem od 100ms)
}
})();
U ovom primjeru, drop(2)
preskače prva dva broja iz niza.
toArray()
Pomoćnik toArray()
konzumira cijeli asinkroni iterabil i skuplja sve elemente u polje. Vraća promise koji se rješava u polje koje sadrži sve elemente.
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); // Izlaz: [1, 2, 3, 4, 5]
})();
U ovom primjeru, toArray()
skuplja sve brojeve iz niza u polje.
forEach()
Pomoćnik forEach()
izvršava zadanu funkciju jednom za svaki element u asinkronom iterabilu. On *ne* vraća novi asinkroni iterabil, već izvršava funkciju s nuspojavama. To može biti korisno za izvođenje operacija poput zapisivanja (logging) ili ažuriranja korisničkog sučelja.
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");
})();
// Izlaz: Value: 1, Value: 2, Value: 3, forEach completed
some()
Pomoćnik some()
testira prolazi li barem jedan element u asinkronom iterabilu test implementiran zadanom funkcijom. Vraća promise koji se rješava u booleovu vrijednost (true
ako barem jedan element zadovoljava uvjet, inače 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); // Izlaz: Has even number: true
})();
every()
Pomoćnik every()
testira prolaze li svi elementi u asinkronom iterabilu test implementiran zadanom funkcijom. Vraća promise koji se rješava u booleovu vrijednost (true
ako svi elementi zadovoljavaju uvjet, inače 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); // Izlaz: Are all even: true
})();
find()
Pomoćnik find()
vraća prvi element u asinkronom iterabilu koji zadovoljava zadanu testnu funkciju. Ako nijedna vrijednost ne zadovoljava testnu funkciju, vraća se undefined
. Vraća promise koji se rješava u pronađeni element ili 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); // Izlaz: First even number: 2
})();
reduce()
Pomoćnik reduce()
izvršava korisnički definiranu "reducer" povratnu funkciju na svakom elementu asinkronog iterabila, redom, prosljeđujući povratnu vrijednost iz izračuna na prethodnom elementu. Konačni rezultat izvršavanja reducera preko svih elemenata je jedna vrijednost. Vraća promise koji se rješava u konačnu akumuliranu vrijednost.
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); // Izlaz: Sum: 15
})();
Praktični primjeri i slučajevi upotrebe
Async Iterator Helpers vrijedni su u različitim scenarijima. Istražimo neke praktične primjere:
1. Obrada podataka sa streaming API-ja
Zamislite da gradite nadzornu ploču za vizualizaciju podataka u stvarnom vremenu koja prima podatke sa streaming API-ja. API neprestano šalje ažuriranja, a vi trebate obraditi ta ažuriranja kako biste prikazali najnovije informacije.
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);
// Pretpostavljajući da API šalje JSON objekte odvojene novim redovima
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'; // Zamijenite sa svojim URL-om API-ja
const dataStream = fetchDataFromAPI(apiURL);
// Obradite tok podataka
(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);
// Ažurirajte nadzornu ploču obrađenim podacima
}
})();
U ovom primjeru, fetchDataFromAPI
dohvaća podatke sa streaming API-ja, parsira JSON objekte i daje ih kao asinkroni iterabil. Pomoćnik filter
odabire samo metrike, a pomoćnik map
transformira podatke u željeni format prije ažuriranja nadzorne ploče.
2. Čitanje i obrada velikih datoteka
Pretpostavimo da trebate obraditi veliku CSV datoteku koja sadrži podatke o kupcima. Umjesto učitavanja cijele datoteke u memoriju, možete koristiti Async Iterator Helpers za obradu dio po dio.
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'; // Zamijenite putanjom do vaše datoteke
const lines = readLinesFromFile(filePath);
// Obradite retke
(async () => {
for await (const customerData of lines.drop(1).map(line => line.split(',')).filter(data => data[2] === 'USA')) {
console.log('Customer from USA:', customerData);
// Obradite podatke o kupcima iz SAD-a
}
})();
U ovom primjeru, readLinesFromFile
čita datoteku redak po redak i daje svaki redak kao asinkroni iterabil. Pomoćnik drop(1)
preskače zaglavlje, pomoćnik map
dijeli redak u stupce, a pomoćnik filter
odabire samo kupce iz SAD-a.
3. Rukovanje događajima u stvarnom vremenu
Async Iterator Helpers mogu se također koristiti za rukovanje događajima u stvarnom vremenu iz izvora poput WebSocketsa. Možete stvoriti asinkroni iterabil koji emitira događaje kako stižu, a zatim koristiti pomoćnike za obradu tih događaja.
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); // Riješite s null kada se veza zatvori
}
});
}
} finally {
ws.close();
}
}
const websocketURL = 'wss://example.com/events'; // Zamijenite svojim WebSocket URL-om
const eventStream = createWebSocketStream(websocketURL);
// Obradite tok događaja
(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);
// Obradite događaj prijave korisnika
}
})();
U ovom primjeru, createWebSocketStream
stvara asinkroni iterabil koji emitira događaje primljene s WebSocketa. Pomoćnik filter
odabire samo događaje prijave korisnika, a pomoćnik map
transformira podatke u željeni format.
Prednosti korištenja Async Iterator Helpers
- Poboljšana čitljivost i održivost koda: Async Iterator Helpers promiču funkcionalan i kompozabilan stil programiranja, čineći vaš kod lakšim za čitanje, razumijevanje i održavanje. Lančana priroda pomoćnika omogućuje vam da izrazite složene cjevovode za obradu podataka na sažet i deklarativan način.
- Učinkovita upotreba memorije: Async Iterator Helpers obrađuju tokove podataka lijeno (lazily), što znači da obrađuju podatke samo po potrebi. To može značajno smanjiti upotrebu memorije, posebno pri radu s velikim skupovima podataka ili kontinuiranim tokovima podataka.
- Poboljšane performanse: Obradom podataka u toku, Async Iterator Helpers mogu poboljšati performanse izbjegavanjem potrebe za učitavanjem cijelog skupa podataka u memoriju odjednom. To može biti posebno korisno za aplikacije koje rukuju velikim datotekama, podacima u stvarnom vremenu ili streaming API-jima.
- Pojednostavljeno asinkrono programiranje: Async Iterator Helpers apstrahiraju složenost asinkronog programiranja, olakšavajući rad s asinkronim tokovima podataka. Ne morate ručno upravljati promiseima ili povratnim pozivima (callbacks); pomoćnici rukuju asinkronim operacijama iza scene.
- Kompozabilan i ponovno iskoristiv kod: Async Iterator Helpers dizajnirani su da budu kompozabilni, što znači da ih možete lako lančano povezivati kako biste stvorili složene cjevovode za obradu podataka. To promiče ponovnu upotrebu koda i smanjuje dupliciranje koda.
Podrška u preglednicima i runtime okruženjima
Async Iterator Helpers su još uvijek relativno nova značajka u JavaScriptu. Krajem 2024. godine, nalaze se u 3. fazi TC39 procesa standardizacije, što znači da će vjerojatno biti standardizirani u bliskoj budućnosti. Međutim, još uvijek nisu nativno podržani u svim preglednicima i verzijama Node.js-a.
Podrška u preglednicima: Moderni preglednici poput Chromea, Firefoxa, Safarija i Edgea postupno dodaju podršku za Async Iterator Helpers. Možete provjeriti najnovije informacije o kompatibilnosti preglednika na web stranicama kao što je Can I use... da biste vidjeli koji preglednici podržavaju ovu značajku.
Podrška u Node.js-u: Novije verzije Node.js-a (v18 i novije) pružaju eksperimentalnu podršku za Async Iterator Helpers. Da biste ih koristili, možda ćete morati pokrenuti Node.js s zastavicom --experimental-async-iterator
.
Polyfills: Ako trebate koristiti Async Iterator Helpers u okruženjima koja ih nativno ne podržavaju, možete koristiti polyfill. Polyfill je dio koda koji pruža nedostajuću funkcionalnost. Dostupno je nekoliko polyfill biblioteka za Async Iterator Helpers; popularna opcija je biblioteka core-js
.
Implementacija prilagođenih asinkronih iteratora
Iako Async Iterator Helpers pružaju prikladan način za obradu postojećih asinkronih iterabila, ponekad ćete možda morati stvoriti vlastite prilagođene asinkrone iteratore. To vam omogućuje da rukujete podacima iz različitih izvora, kao što su baze podataka, API-ji ili datotečni sustavi, na streaming način.
Da biste stvorili prilagođeni asinkroni iterator, trebate implementirati metodu @@asyncIterator
na objektu. Ova metoda treba vratiti objekt s metodom next()
. Metoda next()
treba vratiti promise koji se rješava u objekt sa svojstvima value
i done
.
Evo primjera prilagođenog asinkronog iteratora koji dohvaća podatke s paginiranog API-ja:
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'; // Zamijenite svojim URL-om API-ja
const paginatedData = fetchPaginatedData(apiBaseURL);
// Obradite paginirane podatke
(async () => {
for await (const item of paginatedData) {
console.log('Item:', item);
// Obradite stavku
}
})();
U ovom primjeru, fetchPaginatedData
dohvaća podatke s paginiranog API-ja, dajući svaku stavku kako je dohvaćena. Asinkroni iterator rukuje logikom paginacije, olakšavajući konzumiranje podataka na streaming način.
Potencijalni izazovi i razmatranja
Iako Async Iterator Helpers nude brojne prednosti, važno je biti svjestan nekih potencijalnih izazova i razmatranja:
- Rukovanje pogreškama: Pravilno rukovanje pogreškama ključno je pri radu s asinkronim tokovima podataka. Morate rukovati potencijalnim pogreškama koje se mogu dogoditi tijekom dohvaćanja, obrade ili transformacije podataka. Korištenje
try...catch
blokova i tehnika rukovanja pogreškama unutar vaših asinkronih pomoćnika iteratora je ključno. - Otkazivanje: U nekim scenarijima, možda ćete morati otkazati obradu asinkronog iterabila prije nego što se u potpunosti konzumira. To može biti korisno pri radu s dugotrajnim operacijama ili tokovima podataka u stvarnom vremenu gdje želite zaustaviti obradu nakon što je ispunjen određeni uvjet. Implementacija mehanizama za otkazivanje, poput korištenja
AbortController
, može vam pomoći u učinkovitom upravljanju asinkronim operacijama. - Povratni pritisak (Backpressure): Kada se radi s tokovima podataka koji proizvode podatke brže nego što se mogu konzumirati, povratni pritisak postaje briga. Povratni pritisak odnosi se na sposobnost potrošača da signalizira proizvođaču da uspori brzinu kojom se podaci emitiraju. Implementacija mehanizama povratnog pritiska može spriječiti preopterećenje memorije i osigurati da se tok podataka obrađuje učinkovito.
- Debugiranje: Debugiranje asinkronog koda može biti izazovnije od debugiranja sinkronog koda. Pri radu s Async Iterator Helpers, važno je koristiti alate i tehnike za debugiranje kako biste pratili tijek podataka kroz cjevovod i identificirali sve potencijalne probleme.
Najbolje prakse za korištenje Async Iterator Helpers
Da biste maksimalno iskoristili Async Iterator Helpers, razmotrite sljedeće najbolje prakse:
- Koristite opisna imena varijabli: Odaberite opisna imena varijabli koja jasno ukazuju na svrhu svakog asinkronog iterabila i pomoćnika. To će vaš kod učiniti lakšim za čitanje i razumijevanje.
- Držite pomoćne funkcije sažetima: Držite funkcije proslijeđene Async Iterator Helpersima što je moguće sažetijima i fokusiranijima. Izbjegavajte izvođenje složenih operacija unutar tih funkcija; umjesto toga, stvorite zasebne funkcije za složenu logiku.
- Lančano povezujte pomoćnike za čitljivost: Lančano povezujte Async Iterator Helpers kako biste stvorili jasan i deklarativan cjevovod za obradu podataka. Izbjegavajte pretjerano gniježđenje pomoćnika, jer to može otežati čitanje vašeg koda.
- Rukujte pogreškama graciozno: Implementirajte pravilne mehanizme za rukovanje pogreškama kako biste uhvatili i obradili potencijalne pogreške koje se mogu dogoditi tijekom obrade podataka. Pružite informativne poruke o pogreškama kako biste pomogli u dijagnosticiranju i rješavanju problema.
- Temeljito testirajte svoj kod: Temeljito testirajte svoj kod kako biste osigurali da ispravno rukuje različitim scenarijima. Napišite jedinične testove (unit tests) kako biste provjerili ponašanje pojedinih pomoćnika i integracijske testove kako biste provjerili cjelokupni cjevovod za obradu podataka.
Napredne tehnike
Sastavljanje prilagođenih pomoćnika
Možete stvoriti vlastite prilagođene pomoćnike asinkronih iteratora sastavljanjem postojećih pomoćnika ili izgradnjom novih od nule. To vam omogućuje da prilagodite funkcionalnost svojim specifičnim potrebama i stvorite ponovno iskoristive komponente.
async function* takeWhile(asyncIterable, predicate) {
for await (const value of asyncIterable) {
if (!predicate(value)) {
break;
}
yield value;
}
}
// Primjer upotrebe:
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);
}
})();
Kombiniranje više asinkronih iterabila
Možete kombinirati više asinkronih iterabila u jedan asinkroni iterabil koristeći tehnike poput zip
ili merge
. To vam omogućuje da istovremeno obrađujete podatke iz više izvora.
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];
}
}
// Primjer upotrebe:
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);
}
})();
Zaključak
JavaScript Async Iterator Helpers pružaju moćan i elegantan način za obradu asinkronih tokova podataka. Nude funkcionalan i kompozabilan pristup manipulaciji podacima, olakšavajući izgradnju složenih cjevovoda za obradu podataka. Razumijevanjem temeljnih koncepata asinkronih iteratora i asinkronih iterabila te ovladavanjem različitim pomoćnim metodama, možete značajno poboljšati učinkovitost i održivost vašeg asinkronog JavaScript koda. Kako podrška u preglednicima i runtime okruženjima nastavlja rasti, Async Iterator Helpers postat će ključan alat za moderne JavaScript programere.