Javascript - Entendendo Generators em 3 Minutos
Tags: javascript, generators, node, advanced
Published: 2020-07-09 02:05:11

---
title: Javascript - Entendendo Generators em 3 Minutos
published: true
description: Uma forma prática de aprender sobre Generators 
tags: javascript, generators, node, advanced
//cover_image: https://direct_url_to_image.jpg
---

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:

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

```

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:

```javascript
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 }
```


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`:


```javascript
let iterator2 = firstGenerator(3);
for( const item of iterator2 ) { 
    console.log(item)
}
```

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`

```javascript
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')
```

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

<blockquote>
<i>
    Esse exemplo é de longe o que eu mais gosto.
</i><small>
</small>
<br/>
    <small>- Nota do tradutor</small>
</blockquote>


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`:

```javascript
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() )
}
```


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](https://medium.com/swlh/understand-javascripts-generators-in-3-minutes-8af75c9c4f5f) em inglês no medium.