<h2>Entendendo Async Iterators</h2>
<p>Um <strong>async iterator</strong> é um objeto que implementa o protocolo assíncrono de iteração, permitindo percorrer dados que chegam de forma assíncrona. Diferentemente dos iteradores comuns, ele retorna uma Promise que resolve para <code>{ value, done }</code>.</p>
<p>Para ser um async iterator, um objeto precisa implementar o método <code>[Symbol.asyncIterator]()</code>, que retorna o próprio iterator com um método <code>next()</code> que retorna uma Promise. Isso é fundamental quando trabalhamos com fluxos de dados, APIs ou leitura de arquivos que não estão imediatamente disponíveis.</p>
<pre><code class="language-javascript">// Exemplo: Iterator assíncrono simples
const asyncIterator = {
counter: 0,
[Symbol.asyncIterator]() {
return this;
},
async next() {
this.counter++;
if (this.counter <= 3) {
return { value: Item ${this.counter}, done: false };
}
return { done: true };
}
};
// Usando for await...of
(async () => {
for await (const item of asyncIterator) {
console.log(item); // Item 1, Item 2, Item 3
}
})();</code></pre>
<h2>Async Generators na Prática</h2>
<p>Um <strong>async generator</strong> é uma função que combina <code>async</code> e <code>function*</code>, permitindo pausar a execução com <code>await</code> e retornar valores com <code>yield</code>. É a forma mais elegante e legível de criar async iterators.</p>
<p>Generators assíncrono são especialmente úteis para consumir APIs, processar grandes volumes de dados ou implementar padrões de produção-consumo. A função <code>async function*</code> retorna automaticamente um async iterator quando chamada.</p>
<pre><code class="language-javascript">// Exemplo: Fetchando dados paginados
async function* fetchPaginatedData(apiUrl, pageSize) {
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(${apiUrl}?page=${page}&limit=${pageSize});
const data = await response.json();
if (data.items.length === 0) {
hasMore = false;
} else {
for (const item of data.items) {
yield item;
}
page++;
}
}
}
// Consumindo
(async () => {
for await (const item of fetchPaginatedData('https://api.example.com/users', 10)) {
console.log(item.name);
}
})();</code></pre>
<h3>Exemplo com Leitura de Arquivo</h3>
<pre><code class="language-javascript">// Lendo arquivo linha por linha (Node.js)
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;
}
}
// Usando
(async () => {
for await (const line of readFileLines('dados.txt')) {
console.log(line);
}
})();</code></pre>
<h2>Padrões Avançados e Casos de Uso</h2>
<h3>Composição e Transformação</h3>
<p>Você pode encadear múltiplos async generators para criar pipelines de dados elegantes. Isso é particularmente poderoso para processamento ETL (Extract, Transform, Load).</p>
<pre><code class="language-javascript">// Filtrando dados
async function* filter(asyncIterable, predicate) {
for await (const item of asyncIterable) {
if (await predicate(item)) {
yield item;
}
}
}
// Transformando dados
async function* map(asyncIterable, transform) {
for await (const item of asyncIterable) {
yield await transform(item);
}
}
// Usando pipeline
(async () => {
const users = async function* () {
yield { id: 1, name: 'Alice', age: 28 };
yield { id: 2, name: 'Bob', age: 17 };
yield { id: 3, name: 'Charlie', age: 35 };
};
const adults = filter(users(), user => user.age >= 18);
const names = map(adults, user => user.name.toUpperCase());
for await (const name of names) {
console.log(name); // ALICE, CHARLIE
}
})();</code></pre>
<h3>Tratamento de Erros</h3>
<p>Erros em async generators devem ser tratados com try/catch tanto na função quanto durante a consumição, garantindo robustez.</p>
<pre><code class="language-javascript">async function* safeDataFetch(urls) {
for (const url of urls) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(HTTP ${response.status});
yield await response.json();
} catch (error) {
console.error(Erro ao buscar ${url}:, error.message);
yield null; // ou use continue; para pular
}
}
}
(async () => {
for await (const data of safeDataFetch(['url1', 'url2', 'url3'])) {
if (data) console.log(data);
}
})();</code></pre>
<h2>Performance e Boas Práticas</h2>
<p>Async generators são eficientes em memória porque processam um item por vez, ideal para grandes datasets. Nunca coloque toda a lógica assíncrona dentro de um único <code>await</code> no meio do generator — isso pode travar a iteração.</p>
<blockquote><p><strong>Dica importante:</strong> Use <code>for await...of</code> apenas quando realmente precisar de assincronicidade. Para arrays normais, continue usando <code>for</code> ou métodos como <code>map()</code> e <code>filter()</code>.</p></blockquote>
<pre><code class="language-javascript"></code></pre>
<h2>Conclusão</h2>
<p>Os principais aprendizados são: (1) <strong>Async iterators e generators</strong> oferecem uma forma elegante e eficiente de trabalhar com dados assíncrono em JavaScript, especialmente quando combinados com <code>for await...of</code>; (2) <strong>generators assíncrono</strong> (<code>async function*</code>) são a abordagem recomendada na maioria dos casos por sua legibilidade e capacidade de pausar/resumir com <code>await</code> e <code>yield</code>; (3) <strong>padrões de composição</strong> (filter, map, etc.) permitem criar pipelines robustos de processamento de dados sem carregar tudo na memória.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function*" target="_blank" rel="noopener noreferrer">MDN: Async Iterators and Generators</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of" target="_blank" rel="noopener noreferrer">MDN: for await...of</a></li>
<li><a href="https://github.com/tc39/proposal-async-iteration" target="_blank" rel="noopener noreferrer">TC39 Proposal: Async Iteration</a></li>
<li><a href="https://javascript.info/async-generators" target="_blank" rel="noopener noreferrer">JavaScript.info: Async Generators</a></li>
<li><a href="https://eloquentjavascript.net/" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Cap. 11: Asynchronous Programming</a></li>
</ul>