Resumo : neste tutorial, você aprenderá sobre os iteradores assíncronos JavaScript que permitem acessar dados assíncronos sequencialmente.
Introdução aos iteradores assíncronos JavaScript
ES6 introduziu a interface do iterador que permite acessar dados sequencialmente. O iterador é adequado para acessar fontes de dados síncronas, como arrays , sets e maps .
O método principal de uma interface iteradora é aquele next()
que retorna o {value, done}
objeto, onde done
é um booleano que indica se o final da sequência foi atingido e value
é o valor produzido na sequência.
Os dados síncronos significam que o próximo value
na sequência e o done
estado são conhecidos no momento em que o next()
método retorna.
Além das fontes de dados síncronas, o JavaScript geralmente precisa acessar fontes de dados assíncronas, como acesso de E/S. Para fontes de dados assíncronas, o estado value
e done
do iterador geralmente é desconhecido no momento em que o next()
método retorna.
Para lidar com as fontes de dados assíncronas, ES2018 introduziu a interface do iterador assíncrono (ou iterador assíncrono).
Um iterador assíncrono é como um iterador, exceto que seu next()
método retorna uma promessa que é resolvida para o {value, done}
objeto.
A seguir ilustra a Sequence
classe que implementa a interface do iterador. (Confira o tutorial do iterador para obter mais informações sobre como implementar Sequence
a classe.)
class Sequence {
constructor(start = 0, end = Infinity, interval = 1) {
this.start = start;
this.end = end;
this.interval = interval;
}
[Symbol.iterator]() {
let counter = 0;
let nextIndex = this.start;
return {
next: () => {
if (nextIndex <= this.end) {
let result = {
value: nextIndex,
done: false
}
nextIndex += this.interval;
counter++;
return result;
}
return {
value: counter,
done: true
};
}
}
}
}
Linguagem de código: JavaScript ( javascript )
Para tornar esta Sequence
classe assíncrona, você precisa modificá-la da seguinte forma:
- Use o
Symbol.asyncIterator
em vez doSymbol.iterator
- Retorne uma promessa do
next()
método.
O código a seguir transforma a Sequence
classe em AsyncSequence
classe:
class AsyncSequence {
constructor(start = 0, end = Infinity, interval = 1) {
this.start = start;
this.end = end;
this.interval = interval;
}
[Symbol.asyncIterator]() {
let counter = 0;
let nextIndex = this.start;
return {
next: async () => {
if (nextIndex <= this.end) {
let result = {
value: nextIndex,
done: false
}
nextIndex += this.interval;
counter++;
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result);
}, 1000);
});
}
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
value: counter,
done: true
});
}, 1000);
});
}
}
}
}
Linguagem de código: JavaScript ( javascript )
O AsyncSequence
retorna o próximo número na sequência a cada 1 segundo.
A for await...of
declaração
Para iterar sobre um objeto iterável assíncrono, ES2018 introduziu a for await...of
instrução:
for await (variable of iterable) {
// statement
}
Linguagem de código: JavaScript ( javascript )
Como podemos usar a await
palavra-chave apenas em uma async
função, podemos criar um IIFE assíncrono , pois usa a AsyncSequence
classe da seguinte maneira:
(async () => {
let seq = new AsyncSequence(1, 10, 1);
for await (let value of seq) {
console.log(value);
}
})();
Linguagem de código: JavaScript ( javascript )
Saída (cada número é retornado a cada segundo)
1
2
3
4
5
6
7
8
9
10
Linguagem de código: JavaScript ( javascript )
A tabela a seguir ilustra as diferenças entre os iteradores e os iteradores assíncronos:
# | Iteradores | Iteradores assíncronos |
---|---|---|
Símbolo bem conhecido | Symbol.iterator |
Symbol.asyncIterator |
next() o valor de retorno é |
{value, done } |
Promise que resolve{value, done} |
Instrução de loop | for...of |
for await...of |