Descubra a função mais poderosa do JavaScript que você provavelmente nem sabia da existência
Node.js e JavaScript foram projetados para executar aplicações de alto poder de processamento usando quase nada de recursos. O conceito-chave é processamento sob demanda: ao invés de acumular dados em memória, você os processa conforme necessário.
Uma Generator Function é uma função especial marcada com um asterisco (*) que pode retornar múltiplos resultados - por isso o nome "função geradora". Para gerar esses dados você usa a palavra-chave yield, que notifica quem está consumindo essa função geradora que um valor foi retornado.
// 📚 CONCEITO: Generator Function básica
// Pense numa máquina de venda que entrega um produto por vez
function* simpleGenerator() {
yield 1; // 🎯 "Entrega" o primeiro valor e PAUSA
yield 2; // 🎯 "Entrega" o segundo valor e PAUSA
yield 3; // 🎯 "Entrega" o terceiro valor e PAUSA
return 'fim'; // 🏁 Sinaliza que terminou
}
// 🔧 PASSO 1: Criando o iterador (como inserir moeda na máquina)
const iterator = simpleGenerator();
// 🔧 PASSO 2: Consumindo valores um por vez (como apertar o botão)
console.log(iterator.next()); // { value: 1, done: false } ← Primeiro produto
console.log(iterator.next()); // { value: 2, done: false } ← Segundo produto
console.log(iterator.next()); // { value: 3, done: false } ← Terceiro produto
console.log(iterator.next()); // { value: 'fim', done: true } ← Máquina vazia
// 💡 ANALOGIA: Como uma esteira de produção que entrega um item por vez
// ao invés de entregar todos de uma vez numa caixa gigante
"Tá, mas para que você retornaria mais de um valor de uma função em JavaScript? Por que não só retornar um array com todos os itens dentro?" Essa é a maior dúvida entre desenvolvedores, então vamos entender o problema real.
// ❌ PROBLEMA: Array gigante na memória
// Imagine encher uma piscina inteira antes de usar uma gota
function getAllUsers() {
const users = []; // 🏊 "Piscina" que vai crescer absurdamente
// Simula buscar 1 milhão de usuários DE UMA VEZ
for (let i = 0; i < 1000000; i++) {
users.push({
id: i,
name: 'User ' + i,
email: 'user' + i + '@email.com'
});
}
return users; // 🔥 BOOM! 200MB+ na memória
}
// ✅ SOLUÇÃO: Generator = torneira que pinga sob demanda
// Imagine uma torneira: só sai água quando você abre
function* getAllUsersStream() {
// Processa usuários em lotes pequenos de 100
for (let batch = 0; batch < 10000; batch++) {
for (let i = 0; i < 100; i++) {
const userId = batch * 100 + i;
yield { // 💧 Uma "gota" por vez
id: userId,
name: 'User ' + userId,
email: 'user' + userId + '@email.com'
};
}
// 🎯 AQUI: Poderia pausar, buscar do banco, fazer rate limiting
}
}
// 🎯 USO INTELIGENTE: Só processa o que precisa
for (const user of getAllUsersStream()) {
if (user.id > 5000) break; // 🛑 Para quando não precisar mais
console.log(user.name);
// 💡 Só usou 5000 usuários, economizou 195MB de RAM!
}
// 📊 COMPARAÇÃO:
// Array: 1M users = ~200MB RAM + tempo de criação
// Generator: 5K users = ~1MB RAM + parada instantânea
Pense em como funciona o processamento de um arquivo CSV: você lê a primeira linha do arquivo, transforma em JSON e usa o yield
para falar: "Olha, essa linha está pronta! Quem estiver escutando, usa aí que eu vou para o próximo".
// 🏭 ANALOGIA: Linha de produção vs estoque gigante
function* processCSVLine() {
const lines = ['nome,idade', 'João,25', 'Maria,30', 'Pedro,28'];
for (let i = 1; i < lines.length; i++) { // Pula header
const [name, age] = lines[i].split(',');
// 🔄 PROCESSO: Transforma linha em objeto
const user = {
name: name.trim(),
age: parseInt(age),
processedAt: new Date().toISOString()
};
// 📤 "MANDA PRA FRENTE": Entrega o produto processado
yield user;
// 💡 Aqui poderia ter: validação, chamada de API, rate limiting...
console.log(`✅ Processado: ${user.name}`);
}
return 'Processamento concluído!';
}
// 🎯 CONSUMO: Recebe produtos conforme ficam prontos
for (const user of processCSVLine()) {
// Recebe usuário já processado
console.log(`Recebido: ${user.name}, ${user.age} anos`);
// Poderia salvar no banco, enviar email, etc.
// SEM esperar todos os outros terminarem!
}
// 💡 VANTAGEM: "Eu consegui um resultado aqui, eu mando para frente,
// já pego o próximo, mando para frente e já era"
Agora você entende o conceito fundamental que vai transformar como você programa em JavaScript!