Javascript

JavaScript Generators e onde usá-los

Veja como e onde podemos aproveitar os Generators no JavaScript para melhorar o nosso código.

há 6 anos 10 meses

Formação Desenvolvedor JavaScript
Conheça a formação em detalhes

Olá, Web Developers!

Anteriormente escrevi aqui sobre os Generators. Agora vamos ver duas das principais situações onde eles vêm sendo bastante utilizados.

Iterators

Iterator é um objeto que nos fornece o método next() para acessar cada um dos valores que ele contém. Um Array e uma String já possuem Iterators por natureza. Por exemplo: O Iterator da String "TreinaWeb" nos retornaria uma letra por vez a cada execução do método next().

Iterators são criados com o Symbol @@iterator, mas também podemos usar Generators para criá-los de uma maneira bem mais simples:

function* fibonacci(){
    var n1 = 1,
        n2 = 1;
    while(true){
        var current = n2;
        n2 = n1;
        n1 += current;
        yield current;
    }
}

var fib = fibonacci();
console.log(fib.next()); // 1
console.log(fib.next()); // 1
console.log(fib.next()); // 2
console.log(fib.next()); // 3
console.log(fib.next()); // 5

Fluxo Assíncrono

Já que o Generator para a execução e nos dá a possibilidade escolhermos quando continuar, ele pode ser de grande ajuda em códigos assíncronos. Muitos desenvolvedores estão utilizando-o para fazer com que códigos com Promises fiquem mais parecidos visualmente com um código síncrono.

Vamos imaginar a seguinte situação:

function func1(number){
    return new Promise(resolve =>{
        setTimeout(() => resolve(77 + number) , 1000)
    })
}

function func2(number){
    return new Promise(resolve =>{
        setTimeout(() => resolve(22 + number) , 1000)
    })
}

function func3(number){
    return new Promise(resolve =>{
        setTimeout(() => resolve(14 * number) , 1000)
    })
}

// Usando as funções
func1(4)
   .then(number => {
        console.log('Hello');
        return func2(number);
   })
   .then(number => {
        console.log('World');
        return func3(number);
   })
   .then(result => console.log(result))

Fizemos um exemplo bem genérico, onde temos três funções assíncronas, e entre as respostas delas, fazemos uma operação com console.log().

Você pode imaginar isso como, por exemplo, fazer requisição a um servidor, processar os dados, fazer outra requisição com os dados processados, receber os dados e finalmente, exibí-los na tela.

Veja como podemos deixar com um visual mais parecido com código síncrono, usando a biblioteca co:

var co = require('co');

// As funções de antes
co(function* (){
  var a = yield func1(4);

  console.log('Hello');
  var b = yield func2(a);

  console.log('World');
  var c = yield func3(b);

  console.log(c)
})

Criamos uma função anônima como Generator e a passamos para a função co da biblioteca que importamos. A cada execução de uma Promise, passamos o yield junto. Na linha seguinte podemos continuar escrevendo normalmente, como um código síncrono comum. Nada de ficar encadeando then.

Esse comportamento pode ser feito com o Async/Await. A maioria dos navegadores modernos já estão dando suporte e o Node.js já suporta desde a versão 7.

Concluindo

Os Generators já possuem um bom suporte nos navegadores modernos. Eles nos possibilitam trabalhar de novas formas, e cada vez mais a forma como escrevemos JavaScript vem sendo mudada.

Como sempre, em programação podemos fazer a mesma coisa de várias maneiras, e o Generator é uma poderosa adição ao nosso arsenal. É uma boa ferramenta para trabalharmos com código assíncrono.

Caso você esteja interessado em saber mais sobre código assíncrono, programação reativa e funcional, veja o nosso curso de RxJS.

RxJS - Programação reativa
Curso RxJS - Programação reativa
Conhecer o curso

Autor(a) do artigo

Akira Hanashiro
Akira Hanashiro

Graduado em Análise e Desenvolvimento de Sistemas, Pós-graduado em Projetos e Desenvolvimento de Aplicações Web e MBA em Machine Learning. Especializado em Front End e curte desenvolvimento de jogos.

Todos os artigos

Artigos relacionados Ver todos