Geradores Assíncronos - JavaScript
Os iteradores assíncronos nos permitem criar geradores assíncronos. Eles possibilitam o uso do operador await
Para criar um gerador assíncrono, basta adicionar o operador async
async function* nomeDaFuncaoGeradora() {
yield valorRetornado;
}
Vamos considerar um gerador simples:
async function* generatePersonAsync() {
yield "Tom";
}
Aqui, definimos o gerador assíncrono generatePersonAsync
Uma característica dos geradores assíncronos é que, ao chamar seu método next()
Promise
Promise
{ value, done }
done
Por exemplo, considerando o gerador assíncrono definido acima:
async function* generatePersonAsync() {
yield "Tom";
}
const personGenerator = generatePersonAsync();
personGenerator.next(); // Promise
Aqui, ao chamar o método next()
then()
const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data)); // {value: "Tom", done: false}
E ao acessar a propriedade value do objeto retornado pela promise, podemos obter os dados:
const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data.value)); // Tom
Podemos usar o operador await
next()
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();
A saída no console será:
Tom Sam Bob
Como o gerador assíncrono é um iterador assíncrono, também podemos obter seus dados usando o loop 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
Uso do await em Geradores Assíncronos
A principal vantagem dos geradores assíncronos é a possibilidade de usar o operador await
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"]);
Aqui, para simular a obtenção de dados de uma fonte assíncrona, usamos uma promise que, após 2000 milissegundos, retorna um dos elementos do array passado para a função geradora:
yield await new Promise(resolve => setTimeout(() => resolve(person), 2000));