DEV Community

loading...

Javascript - Entendendo Generators em 3 Minutos

Jorge Rafael
Updated on ・3 min read

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.

Discussion (1)

Collapse
urielsouza29 profile image
Uriel dos Santos Souza

Legal