Generatoare Asincrone
Iteratoarele asincrone ne deschid calea către crearea generatoarelor asincrone. Generatoarele asincrone ne permit să folosim operatorul await, să primim și să returnăm date într-un mod asincron.
Pentru a defini un generator asincron, se pune operatorul async înaintea funcției generator:
async function* nume_funcție_generator(){
yield valoare_returnată;
}
Să examinăm cel mai simplu generator:
async function* generatePersonAsync(){
yield "Tom";
}
Aici este definit un generator asincron generatePersonAsync, în care se returnează o singură valoare - șirul "Tom".
Particularitatea generatorului asincron este că la apelarea metodei sale next() se returnează un obiect Promise. Și obiectul Promise, la rândul său, returnează un obiect cu două proprietăți { value, done }, unde value deține valoarea returnată și done indică dacă în generator mai sunt date disponibile.
De exemplu, să luăm generatorul asincron definit mai sus:
async function* generatePersonAsync(){
yield "Tom";
}
const personGenerator = generatePersonAsync();
personGenerator.next(); // Promise
Aici, prin metoda next() obținem un promise. Apoi, prin metoda then() putem obține obiectul din promise:
const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data)); // {value: "Tom", done: false}
Și la accesarea proprietății value a obiectului obținut din promise, putem obține datele:
const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data.value)); // Tom
Cu ajutorul operatorului await putem obține datele din metoda next() a generatorului:
async function* generatePersonAsync(){
yield "Tom";
yield "Sam";
yield "Bob";
}
async function printPeopleAsync(){
const personGenerator = generatePersonAsync();
while(!(person = await personGenerator.next()).done){
console.log(person.value);
}
}
printPeopleAsync();
Output-ul în consolă:
Tom
Sam
Bob
Deoarece generatorul asincron reprezintă un iterator asincron, datele generatorului pot fi, de asemenea, obținute prin ciclul for-await-of:
async function* generatePersonAsync(){
yield "Tom";
yield "Sam";
yield "Bob";
}
async function printPeopleAsync(){
const personGenerator = generatePersonAsync();
for await(person of personGenerator){
console.log(person);
}
}
printPeopleAsync();
// Tom
// Sam
// Bob
await în generatoarele asincrone
Principalul avantaj al generatoarelor asincrone este că putem folosi operatorul await în ele și, în consecință, putem obține date din surse de date care folosesc API-uri asincrone.
async function* generatePersonAsync(people){
for(const person of people)
yield await new Promise(resolve => setTimeout(() => resolve(person), 2000));
}
async function printPeopleAsync(people){
for await (const item of generatePersonAsync(people)) {
console.log(item);
}
}
printPeopleAsync(["Tom", "Sam", "Bob"]);
Aici, pentru a imita obținerea datelor dintr-o sursă de date asincronă, se utilizează un promise care returnează unul dintre elementele array-ului care este transmis în funcția generatorului după 2000 de secunde:
yield await new Promise(resolve => setTimeout(() => resolve(person), 2000));