DEV Community

Jorge Soares
Jorge Soares

Posted on • Updated on

Javascript - Entendendo Generators em 3 Minutos

Geralmente não se fala tanto sobre o generators. Isso ocorre porque existem poucos cenários em que você realmente deseja usá-lo.

No entanto, isso não nega a utilidade do recurso - porque quando esses cenários acabam surgindo, você ficará feliz em ter o generator em seu currículo.

Como a maioria das coisas em programação, o generator é apenas uma ferramenta; Nesse caso, uma ferramenta especializada.

Vamos dar uma olhada em um exemplo de generator em ação e percorrer cada etapa e ver como está funcionando:

function* firstGenerator(range){ 
    let i = 0;
    while(i < range) { 
        i+= 1;
        yield i;
    }
}

Enter fullscreen mode Exit fullscreen mode

Aqui está um generator definido.
Você perceberá que é muito semelhante a uma função normal, exceto pelo fato de termos um * e yield.
O * informa ao JavaScript que esta é uma função geradora.

Discutiremos o yield em um minuto.

Primeiro, vamos mostrar um exemplo do gerador em ação:

let iterator = firstGenerator(3)
iterator // Object [Generator] {}
iterator.next() // { value: 1, done: false }       
iterator.next() // { value: 2, done: false }       
iterator.next() // { value: 3, done: false }       
iterator.next() // { value: undefined, done: true }
Enter fullscreen mode Exit fullscreen mode

Nosso firstGenerator retornou um iterator, dando acesso a um próximo método.

Cada vez que chamamos o next, nossa função executará o código até encontrar uma declaração de rendimento (yield). Quando encontramos uma declaração de rendimento, interromperemos a execução até que a próxima seja chamada novamente. Quando o someGenerator terminar a execução, na próxima vez que chamarmos next, Nós receberemos um objeto que tenha uma chave done com um valor definido como true.

Bem maneiro né?

Bem, o retorno do iterator realmente nos permite fazer mais do que apenas isso.
Também temos acesso a instruções como for… of, bem como a outros métodos de iteração, como o operador spread:

let iterator2 = firstGenerator(3);
for( const item of iterator2 ) { 
    console.log(item)
}
Enter fullscreen mode Exit fullscreen mode

Agora que sabemos o básico sobre o uso de geradores, vamos ver alguns casos de uso.

Um caso de uso comum seria manter o estado de um gerador de ID baseado em um índice.

Digamos que temos um map/object de itens e queremos expor uma função que permita que um usuário
adicione um item a esse mapa, cada item deve ter um ID exclusivo com base na ordem que foi inserido.

Podemos gerar essa instrução de Geração de IDs usando generators

function* idGenerator(){ 
    let i = 0;
    while(true) { 
        i += 1;
        yield `id-${i}`
    }
}

const ourItems = {};
const ourIdGenerator = idGenerator();

function addItem(item) {
    const id = ourIdGenerator.next()
    ourItems[id] = { id, item }
}

addItem('valor a ser guardado')
Enter fullscreen mode Exit fullscreen mode

Outro exemplo seria abstrair o UX Flow em uma única função.

Esse exemplo é de longe o que eu mais gosto.
- Nota do tradutor

Imagine que temos um design de UX; Um usuário clica em um botão, depois fazemos alguns cálculos; depois que os cálculos terminam, queremos mostrar outro botão; depois de clicar nesse botão, fazemos mais alguns cálculos e então atualizamos a janela.

Poderíamos colocar tudo isso em uma única função, mas pode ficar bem confuso.

Em vez disso, como sabemos a ordem na qual nosso design flui, podemos usar generators:

function* UXDesignFlow(){ 
    yield showFirstButton();
    yield showSecondButton();
    yield window.location.reload();
}


function mainApp() { 
    const uxIterator = UXDesignFlow();

    uxIterator.next();
    firstButton.on('click', () => uxIterator.next() )
    secondButton.on('click', () => uxIterator.next() )
}
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, isolamos com êxito nosso fluxo de design e nossa lógica.
Isso facilita o teste, a legibilidade e, consequentemente, a manutenção.

Cada vez que concluímos nossos cálculos, mostramos a próxima etapa na interface do usuário.

Conclusão

Na maioria das vezes você não vai precisar de geradores, mas, quando precisa ficará feliz em ter isso na sua stack, Ele ajuda a abstrair interações e fornecem uma solução limpa para quando é necessário uma execução mais lenta dos valores solicitados.

Conclusão do Tradutor.

Esse artigo é uma tradução quase que direta do Artigo Original em inglês no medium.

Top comments (2)

Collapse
 
urielsouza29 profile image
Uriel dos Santos Souza

Legal

Collapse
 
calastro profile image
Gustavo

Hmm interessante