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.