Õppige asünkroonset iteratsiooni JavaScriptis, kasutades 'for await...of' tsüklit ja kohandatud asünkroonse iteraatori abimeetodeid. Parandage voogedastuse ja andmete töötlemist praktiliste näidetega.
JavaScripti asünkroonse iteraatori abimeetod: For Each – voogedastuse töötlemise iteratsioon
Asünkroonne programmeerimine on kaasaegse JavaScripti arenduse nurgakivi, mis võimaldab rakendustel hallata aeganõudvaid toiminguid ilma peamist lõime blokeerimata. Asünkroonsed iteraatorid, mis võeti kasutusele ECMAScript 2018-s, pakuvad võimsa mehhanismi andmevoogude asünkroonseks töötlemiseks. See blogipostitus süveneb asünkroonsete iteraatorite kontseptsiooni ja näitab, kuidas implementeerida asünkroonset 'for each' abifunktsiooni voogedastuse töötlemise sujuvamaks muutmiseks.
Asünkroonsete iteraatorite mõistmine
Asünkroonne iteraator on objekt, mis vastab AsyncIterator liidesele. See defineerib next() meetodi, mis tagastab lubaduse (promise), mis lahendatakse objektiks, millel on kaks omadust:
value: Järjestuse järgmine väärtus.done: Kahendmuutuja (boolean), mis näitab, kas iteraator on lõpule jõudnud.
Asünkroonseid iteraatoreid kasutatakse tavaliselt andmete tarbimiseks asünkroonsetest allikatest nagu võrguvood, failisüsteemid või andmebaasid. Tsükkel for await...of pakub mugavat süntaksit asünkroonsete itereeritavate objektide läbimiseks.
Näide: failist asünkroonne lugemine
Kujutage ette stsenaariumi, kus peate lugema suurt faili rida-realt ilma peamist lõime blokeerimata. Saate seda teha kasutades asünkroonset iteraatorit:
const fs = require('fs');
const readline = require('readline');
async function* readFileLines(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
yield line;
}
}
async function processFile(filePath) {
for await (const line of readFileLines(filePath)) {
console.log(`Line: ${line}`);
}
}
// Kasutusnäide
processFile('path/to/your/file.txt');
Selles näites on readFileLines asünkroonne generaatorfunktsioon, mis annab (yield) iga failirea selle lugemisel. Funktsioon processFile itereerib seejärel üle ridade, kasutades tsüklit for await...of, töödeldes iga rida asünkroonselt.
Asünkroonse 'For Each' abimeetodi implementeerimine
Kuigi for await...of tsükkel on kasulik, võib see muutuda kohmakaks, kui peate iga voo elemendiga tegema keerulisi toiminguid. Asünkroonne 'for each' abifunktsioon võib seda protsessi lihtsustada, kapseldades iteratsiooniloogika.
Põhiline implementatsioon
Siin on asünkroonse 'for each' funktsiooni põhiline implementatsioon:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
await callback(item);
}
}
See funktsioon võtab argumentideks asünkroonse itereeritava objekti ja tagasikutsefunktsiooni (callback). See itereerib üle itereeritava objekti, kasutades tsüklit for await...of, ja kutsub iga elemendi jaoks välja tagasikutsefunktsiooni. Tagasikutsefunktsioon peaks samuti olema asünkroonne, kui soovite oodata selle lõpuleviimist enne järgmise elemendi juurde liikumist.
Näide: andmete töötlemine API-st
Oletame, et hangite andmeid API-st, mis tagastab elementide voo. Saate kasutada asünkroonset 'for each' abimeetodit iga elemendi töötlemiseks selle saabumisel:
async function* fetchDataStream(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) {
return;
}
// Eeldades, et API tagastab JSON-tükke
const chunk = decoder.decode(value);
const items = JSON.parse(`[${chunk.replace(/\}\{/g, '},{')}]`); //Jaota tükid kehtivaks JSON-massiiviks
for(const item of items){
yield item;
}
}
} finally {
reader.releaseLock();
}
}
async function processItem(item) {
// Simuleeri asünkroonset toimingut
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Asenda oma API lõpp-punktiga
await asyncForEach(fetchDataStream(apiUrl), processItem);
console.log('Finished processing data.');
}
// Kasutusnäide
main();
Selles näites hangib fetchDataStream andmeid API-st ja annab (yield) iga elemendi selle kättesaamisel. Funktsioon processItem simuleerib asünkroonset toimingut iga elemendiga. asyncForEach abimeetod lihtsustab seejärel iteratsiooni ja töötlemise loogikat.
Täiustused ja kaalutlused
Vigade käsitlemine
On ülioluline käsitleda vigu, mis võivad tekkida asünkroonse iteratsiooni käigus. Saate mähkida tagasikutsefunktsiooni try...catch plokki, et püüda ja käsitleda erandeid:
async function asyncForEach(iterable, callback) {
for await (const item of iterable) {
try {
await callback(item);
} catch (error) {
console.error(`Error processing item: ${item}`, error);
// Võite vea uuesti visata või jätkata töötlemist
}
}
}
Samaaegsuse kontroll
Vaikimisi töötleb asünkroonne 'for each' abimeetod elemente järjestikku. Kui peate elemente töötlema samaaegselt, saate kasutada Promise'i kogumit (pool), et piirata samaaegsete toimingute arvu:
async function asyncForEachConcurrent(iterable, callback, concurrency) {
const executing = [];
for await (const item of iterable) {
const p = callback(item).then(() => executing.splice(executing.indexOf(p), 1));
executing.push(p);
if (executing.length >= concurrency) {
await Promise.race(executing);
}
}
await Promise.all(executing);
}
async function processItem(item) {
// Simuleeri asünkroonset toimingut
await new Promise(resolve => setTimeout(resolve, 100));
console.log(`Processing item: ${JSON.stringify(item)}`);
}
async function main() {
const apiUrl = 'https://api.example.com/data'; // Asenda oma API lõpp-punktiga
await asyncForEachConcurrent(fetchDataStream(apiUrl), processItem, 5); // Samaaegsus 5
console.log('Finished processing data.');
}
Selles näites piirab asyncForEachConcurrent samaaegsete tagasikutsete arvu määratud samaaegsuse tasemele. See võib parandada jõudlust suurte andmevoogudega tegelemisel.
Tühistamine
Mõnel juhul võib olla vajalik iteratsiooniprotsess enneaegselt tühistada. Seda saate saavutada kasutades AbortController'it:
async function asyncForEach(iterable, callback, signal) {
for await (const item of iterable) {
if (signal && signal.aborted) {
console.log('Iteration aborted.');
return;
}
await callback(item);
}
}
async function main() {
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => {
controller.abort(); // Tühista 2 sekundi pärast
}, 2000);
const apiUrl = 'https://api.example.com/data'; // Asenda oma API lõpp-punktiga
await asyncForEach(fetchDataStream(apiUrl), processItem, signal);
console.log('Finished processing data.');
}
Selles näites kontrollib asyncForEach funktsioon enne iga iteratsiooni signal.aborted omadust. Kui signaal on tühistatud, peatatakse iteratsioon.
Reaalmaailma rakendused
Asünkroonseid iteraatoreid ja asünkroonset 'for each' abimeetodit saab rakendada laias valikus reaalmaailma stsenaariumides:
- Andmetöötluse torujuhtmed: Suurte andmekogumite töötlemine andmebaasidest või failisüsteemidest.
- Reaalajas andmevood: Andmete käsitlemine veebipesadest (web sockets), sõnumijärjekordadest või andurivõrkudest.
- API tarbimine: Andmete hankimine ja töötlemine API-dest, mis tagastavad elementide vooge.
- Pildi- ja videotöötlus: Suurte meediafailide töötlemine tükkidena.
- Logianalüüs: Suurte logifailide analüüsimine rida-realt.
Näide – rahvusvahelised aktsiaandmed: Kujutage ette rakendust, mis hangib reaalajas aktsiahindu erinevatelt rahvusvahelistelt börsidelt. Asünkroonset iteraatorit saab kasutada andmete voogedastuseks ja asünkroonne 'for each' saab töödelda iga noteeringut, uuendades kasutajaliidest uusimate hindadega. Seda saab kasutada selliste ettevõtete praeguste aktsiahindade kuvamiseks nagu:
- Tencent (Hiina): Suure rahvusvahelise tehnoloogiaettevõtte aktsiaandmete hankimine
- Tata Consultancy Services (India): Juhtiva IT-teenuste ettevõtte aktsiauudiste kuvamine
- Samsung Electronics (Lõuna-Korea): Globaalse elektroonikatootja aktsiahindade esitlemine
- Toyota Motor Corporation (Jaapan): Rahvusvahelise autotootja aktsiahindade jälgimine
Kokkuvõte
Asünkroonsed iteraatorid ja asünkroonne 'for each' abimeetod pakuvad võimsat ja elegantset viisi andmevoogude asünkroonseks töötlemiseks JavaScriptis. Iteratsiooniloogika kapseldamisega saate lihtsustada oma koodi, parandada loetavust ja tõsta oma rakenduste jõudlust. Vigade käsitlemise, samaaegsuse kontrollimise ja tühistamise võimaldamisega saate luua robustseid ja skaleeritavaid asünkroonseid andmetöötluse torujuhtmeid.