JavaScript

Generators e Iteradores em JavaScript na Prática

6 min de leitura

Generators e Iteradores em JavaScript na Prática

Iteradores: A Base de Tudo Um iterador é um objeto JavaScript que implementa o protocolo iterável, permitindo percorrer uma sequência de valores. Todo iterador possui um método que retorna um objeto com duas propriedades: (o valor atual) e (booleano indicando se chegou ao fim). Para entender na prática, considere este exemplo: você precisa criar um iterador que gera números de 1 a 5. Implementamos através de um objeto com o método : Note o e — essa é a forma moderna de trabalhar com generators assíncronos. Gerando IDs Únicos Um padrão muito prático é usar generators para gerar sequências de IDs: ${prefixo}-${contador++} Conclusão Iteradores e generators são ferramentas poderosas que você usará constantemente em JavaScript moderno. Primeiro aprendizado: entender que todo objeto com é iterável, permitindo usar e spread operator. Segundo aprendizado: generators são a forma elegante e prática de criar iteradores, economizando linhas de código e melhorando legibilidade. Terceiro aprendizado: generators assíncronos ( e ) são essenciais para trabalhar

<h2>Iteradores: A Base de Tudo</h2>

<p>Um iterador é um objeto JavaScript que implementa o protocolo iterável, permitindo percorrer uma sequência de valores. Todo iterador possui um método <code>next()</code> que retorna um objeto com duas propriedades: <code>value</code> (o valor atual) e <code>done</code> (booleano indicando se chegou ao fim).</p>

<p>Para entender na prática, considere este exemplo: você precisa criar um iterador que gera números de 1 a 5. Implementamos através de um objeto com o método <code>Symbol.iterator</code>:</p>

<pre><code class="language-javascript">const minhaSequencia = {

valor: 1,

[Symbol.iterator]() {

return {

valor: this.valor,

next: () =&gt; {

if (this.valor &lt;= 5) {

return { value: this.valor++, done: false };

}

return { done: true };

}

};

}

};

for (const num of minhaSequencia) {

console.log(num); // 1, 2, 3, 4, 5

}</code></pre>

<p>Essa implementação é funcional, mas verbosa. Generators resolvem exatamente esse problema oferecendo uma sintaxe muito mais limpa.</p>

<h2>Generators: Iteradores Simplificados</h2>

<p>Um generator é uma função especial que pode pausar sua execução e retomar depois. Você a declara com <code>function*</code> e usa <code>yield</code> para pausar. Quando chamada, retorna um iterador automaticamente.</p>

<p>Aqui está o mesmo exemplo anterior, mas muito mais elegante:</p>

<pre><code class="language-javascript">function* minhaSequencia() {

for (let i = 1; i &lt;= 5; i++) {

yield i;

}

}

for (const num of minhaSequencia()) {

console.log(num); // 1, 2, 3, 4, 5

}</code></pre>

<p>A diferença é notável: o generator faz o mesmo trabalho com menos linhas e maior legibilidade. Quando você chama <code>minhaSequencia()</code>, não executa a função imediatamente — retorna um iterador. Cada vez que <code>next()</code> é chamado (implicitamente no <code>for...of</code>), a execução continua até o próximo <code>yield</code>.</p>

<h3>Dois Casos de Uso Cruciais</h3>

<p><strong>Gerando sequências infinitas</strong>: Você pode criar geradores que produzem valores infinitos sem criar arrays em memória:</p>

<pre><code class="language-javascript">function* infinito() {

let contador = 0;

while (true) {

yield contador++;

}

}

const gen = infinito();

console.log(gen.next().value); // 0

console.log(gen.next().value); // 1

console.log(gen.next().value); // 2</code></pre>

<p><strong>Delegando a outro generator</strong>: Use <code>yield*</code> para reutilizar generators dentro de generators:</p>

<pre><code class="language-javascript">function* geradorA() {

yield 1;

yield 2;

}

function* geradorB() {

yield* geradorA();

yield 3;

}

for (const valor of geradorB()) {

console.log(valor); // 1, 2, 3

}</code></pre>

<h2>Aplicações Práticas no Mundo Real</h2>

<h3>Processando Grandes Arquivos</h3>

<p>Imagine processar um arquivo CSV gigantesco linha por linha sem carregar tudo na memória:</p>

<pre><code class="language-javascript">function* lerArquivoLinhasPorLinhas(conteudo) {

const linhas = conteudo.split(&#039;\n&#039;);

for (const linha of linhas) {

yield linha.trim();

}

}

const dados = &quot;nome,idade\nJoão,25\nMaria,30\nPedro,28&quot;;

for (const linha of lerArquivoLinhasPorLinhas(dados)) {

if (linha &amp;&amp; !linha.startsWith(&#039;nome&#039;)) {

const [nome, idade] = linha.split(&#039;,&#039;);

console.log(${nome} tem ${idade} anos);

}

}</code></pre>

<h3>API com Paginação</h3>

<p>Generators simplificam muito o consumo de APIs paginadas. Você não precisa gerenciar estado manualmente:</p>

<pre><code class="language-javascript">async function* buscarPaginas(url) {

let pagina = 1;

let temProxima = true;

while (temProxima) {

const resposta = await fetch(${url}?page=${pagina});

const dados = await resposta.json();

yield dados.itens;

temProxima = dados.temProxima;

pagina++;

}

}

// Uso:

(async () =&gt; {

for await (const itens of buscarPaginas(&#039;https://api.exemplo.com/dados&#039;)) {

console.log(&#039;Processando&#039;, itens.length, &#039;itens&#039;);

}

})();</code></pre>

<p>Note o <code>async function*</code> e <code>for await...of</code> — essa é a forma moderna de trabalhar com generators assíncronos.</p>

<h3>Gerando IDs Únicos</h3>

<p>Um padrão muito prático é usar generators para gerar sequências de IDs:</p>

<pre><code class="language-javascript">function* gerarIds(prefixo = &#039;ID&#039;) {

let contador = 1;

while (true) {

yield ${prefixo}-${contador++};

}

}

const ids = gerarIds(&#039;USER&#039;);

console.log(ids.next().value); // USER-1

console.log(ids.next().value); // USER-2

console.log(ids.next().value); // USER-3</code></pre>

<h2>Conclusão</h2>

<p>Iteradores e generators são ferramentas poderosas que você usará constantemente em JavaScript moderno. <strong>Primeiro aprendizado</strong>: entender que todo objeto com <code>Symbol.iterator</code> é iterável, permitindo usar <code>for...of</code> e spread operator. <strong>Segundo aprendizado</strong>: generators são a forma elegante e prática de criar iteradores, economizando linhas de código e melhorando legibilidade. <strong>Terceiro aprendizado</strong>: generators assíncronos (<code>async function*</code> e <code>for await...of</code>) são essenciais para trabalhar com fluxos de dados assíncronos como APIs paginadas ou streams.</p>

<p>Dominar esses conceitos não é opcional — é fundamental para escrever código JavaScript eficiente e profissional.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators" target="_blank" rel="noopener noreferrer">MDN: Iterators and Generators</a></li>

<li><a href="https://javascript.info/generators" target="_blank" rel="noopener noreferrer">JavaScript.info: Generators</a></li>

<li><a href="https://tc39.es/ecma262/#sec-generator-objects" target="_blank" rel="noopener noreferrer">ECMAScript Specification: Generator Objects</a></li>

<li><a href="https://eloquentjavascript.net/11_async.html" target="_blank" rel="noopener noreferrer">Eloquent JavaScript - Capítulo sobre Iteradores</a></li>

<li><a href="https://github.com/getify/You-Dont-Know-JS" target="_blank" rel="noopener noreferrer">You Don&#039;t Know JS Yet - Generators &amp; Async Patterns</a></li>

</ul>

Comentários

Mais em JavaScript

Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress
Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress

Introdução aos Testes End-to-End Testes end-to-end (E2E) verificam sua aplica...

Laços em JavaScript: for, while, for...of, for...in e forEach: Do Básico ao Avançado
Laços em JavaScript: for, while, for...of, for...in e forEach: Do Básico ao Avançado

Introdução aos Laços em JavaScript Laços são estruturas fundamentais que perm...

Estruturas de Controle em JavaScript: if, switch e Tratamento de Fluxo: Do Básico ao Avançado
Estruturas de Controle em JavaScript: if, switch e Tratamento de Fluxo: Do Básico ao Avançado

Estruturas Condicionais: A Base da Lógica em JavaScript As estruturas de cont...