Portuguese (Português) translation by Erick Patrick (you can also view the original English article)
O Koa.js é um framework para web, expressivo e de próxima geração, para Node.js, criado pelo pessoal responsável pelos frameworks Express e Connect. O Koa.js lança mão de geradores, que são uma funcionalidade bem recente no JavaScript, e que ainda não chegou às versões estáveis do Node.js. O Koa tem como objetivo lançar mão de geradores para evitar que os desenvolvedores acabem em código espaguete de funções call-backs, diminuindo a ocorrência de erros, tornando-o mais administrável.
Com apenas 550 linhas de código, o Koa é um framework extremamente leve. Ainda assim, o Koa vem com um elegante conjunto de métodos, como os de negociação de conteúdo, redirecionamentos, suporte a proxy, etc., facilitando e acelerando o desenvolvimento, juntamente ao controle granular sobre sua aplicação para Node.
Instalando o Node
Antes de começarmos, você precisará ter a versão 0.11.x
do Node, ou mais recente.
Você pode instalar a versão mais recente do Node usando o módulo N:
1 |
sudo npm install -g n |
2 |
sudo n stable
|
Você pode usar outros módulos da comunidade, como o nvm ou construí-lo a partir do código fonte, a escolha é sua. Note que o N também é um módulo da comunidade.
Para executar um código JavaScript que faz uso de geradores, você precisa prover o semáforo (flag) --harmony
ao executá-lo.
Por exemplo, para executar o código app.js
, digite o seguinte comando:
1 |
node --harmony app.js
|
Ou para evitar que tenha de digitar o semáforo todas as vezes, você pode criar um apelido (alias), usando o seguinte comando:
1 |
alias node="node --harmony" |
Agora, para executar suas aplicações que usam geradores, basta digitar:
1 |
node app.js |
Muito bem! Lembre-se que todo o código desse artigo está disponível no GitHub. Sinta-se livre para fazer uma cópia para você e brincar com ele.
Para entender o Koa, primeiro, você tem de entender os geradores, que são a espinha dorsal do framework.
O Que São Geradores?
Com a EcmaScript 6, os geradores finalmente chegaram à terra mágica do JavaScript. Se você já usou geradores em outras linguagens de programação como o Lua, Python, Scheme, Smalltalk, etc., então você ficará feliz de saber que algo muito semelhante foi implementado no JavaScript.
Os geradores são co-rotinas de primeira classe no JavaScript, isso é, introduzem uma interface de pausa e execução na linguagem. Antes dos geradores, o código inteiro costumava executar do início ao fim, sem uma maneira fácil de parar a execução do código e dar continuidade de onde parou. Agora, sujemos nossas mãos com alguns exemplos.
De acordo com a atual especificação da EcmaScript 6, precisamos usar uma versão diferente de definição de função para criar uma função geradora. Ela se parece com isso:
1 |
var generator_func = function* () { }; |
Aqui, a generator_func
é só uma função geradora vazia.
O que podemos fazer agora é usar a palavra-chave yield
no corpo da função para parar a execução e guardar o estado atual da pilha de execução.
Eis um exemplo simples demonstrando a Soma de uma Progressão Aritmética Infinita:
1 |
var r = 3; |
2 |
|
3 |
function* infinite_ap(a) { |
4 |
for( ; ; ) { |
5 |
a = a + r; |
6 |
yield a; |
7 |
}
|
8 |
}
|
9 |
|
10 |
var sum = infinite_ap(5); |
11 |
|
12 |
console.log(sum.next()); // retorna { value : 8, done : false } |
13 |
console.log(sum.next()); // retorna { value : 11, done: false } |
No código acima, começamos criando uma instância de um iterador, chamado de infinite_ap
, que inclui o um laço infinito e se executado sob condições normais, pode parar a execução.
Depois, salvamos a instância do iterador na variável sum
.
Agora, quando executarmos sum.next()
, ela retornará { value: 8, done: false }
, significando que ela pausou sua execução quando alcançou a declaração yield
retornando value
com o valor de 'a' e done
com o valor de 'false'.
Enquanto a execução não for finalizada, done
continuará retornando 'false'. Assim que a execução estiver finalizada (no caso acima, isso nunca acontece), a função retornará {value: undefined, done: true}
.
Eis uma pequena modificação do trecho de código anterior para demosntrar a finalização da execução:
1 |
var r = 3; |
2 |
|
3 |
function* infinite_ap(a) { |
4 |
for( var i = 0; i < 3 ; i++) { |
5 |
a = a + r ; |
6 |
yield a; |
7 |
} |
8 |
} |
9 |
|
10 |
var sum = infinite_ap(5); |
11 |
|
12 |
console.log(sum.next()); // retorna { value : 8, done : false } |
13 |
console.log(sum.next()); // retorna { value : 11, done: false } |
14 |
console.log(sum.next()); // retorna { value : 14, done: false } |
15 |
console.log(sum.next()); // retorna { value: undefined, done: true } |
Em programas mais complexos, você poderia verificar e usar os valores retornados e o estado done
.
Nota: Usar yield
sem function*
levará a um erro.
Métodos de Geradores Disponíveis
Eis alguns métodos que serão úteis ao lidar com geradores padrão.
Cada um dos métodos abaixo está disponível apenas em uma função geradora e lançará um erro, caso contrário.
next()
Esse método é usado para dar continuidade à execução e os argumentos necessários. Se nada for passado, undefined
é passado como o primeiro argumento.
Exemplo: sum.next(5);
throw()
Esse método é usado para lançar um erro ou exceção em qualquer passo. Ele torna a manipulação de erros muito mais fácil. Lançar um erro pode resultar na finalização da execução de um arquivo, caso não seja manipulado em algum lugar. A forma mais simples de manipular erros é usar try-catch
. Esse método leva um único argumento que pode ser qualquer coisa.
Exemplo: sum.throw(new Error("Isso é um erro"));
Delegando o yield
Delegação de geradores é usado para fornecer um gerador a partir de um gerador existente e pode ser usado para compor geradores e, até mesmo, iterar sobre um gerador.
Ao delegar a outro gerador, o gerador atual para de produzir valores para si próprio e começa a esperar pelos valores do gerador delegado até que ele finalize. Uma vez finalizada a delegação do gerador, o gerador original volta a retornar seus próprios valores.
É quase a mesma coisa que usar um laço for-in
para iterar sobre o gerador, mas as exceções do gerador delegado são propagadas e lançadas pelo método throw
do gerador original, e deveria ser manipulado de acordo. Eis um exemplo:
1 |
var consoleLogThunk = function(msg) { |
2 |
return function() { |
3 |
console.log(msg); |
4 |
}
|
5 |
}
|
6 |
|
7 |
var generator = function*() { |
8 |
yield consoleLogThunk("Yo"); |
9 |
yield consoleLogThunk("Dawg"); |
10 |
yield consoleLogThunk("!!!"); |
11 |
}
|
12 |
|
13 |
var delegator_function = function* () { |
14 |
yield consoleLogThunk("I yielded before delegated yield"); |
15 |
yield* generator(); |
16 |
yield consoleLogThunk("I yielded after delegated yield"); |
17 |
}
|
18 |
|
19 |
var k = delegator_function(); |
20 |
|
21 |
k.next().value(); |
22 |
k.next().value(); |
23 |
k.next().value(); |
24 |
|
25 |
console.log(k.next()); // Se você invocar k.next(), será lançado um erro Type, uma vez que o valor é undefined, que não é uma função |
26 |
Agora que você tem sabe um pouco sobre geradores no JavaScript, você pode usá-los para escrever aplicações muito mais claras e precisas, onde você pode criar códigos de I/O, sem bloquear o processo de verdade.
Passemos para a instalação do Koa e criação de uma aplicação bem simples em Koa.js.
Koa.js:
O Koa é um objeto que contém um vetor de funções geradores de mediador (middlewares), os quais são compostos e executados em pilha a cada requisição.
Instalando Koa
No diretório do seu projeto, execute o comando a seguir.
1 |
npm install koa --save |
Koa será baixado automaticamente e salvo no arquivo package.json
, se existir.
Apesar do pequeno do Koa, ela inclui métodos como limpeza de cache, negociação de conteúdo, suporte a proxy, etc., sem qualquer mediador adicionado.
Eis um exemplo de uma aplicação ola-mundo:
1 |
var koa = require('koa'); |
2 |
var app = koa(); |
3 |
|
4 |
app.use(function *(){ |
5 |
this.body = "Olá Mundo !!!"; |
6 |
});
|
7 |
|
8 |
app.listen(3000); |
Fluxo de Controle do Koa
Koa também implementa o controle de fluxo de ida e volta. Inicialmente, pode ser difícil de entender, mas, uma vez que conseguir compreender o exemplo abaixo, as coisas ficarão mais claras.
Eis um exemplo de controle de fluxo no Koa:
1 |
var koa = require('koa')(); |
2 |
|
3 |
koa.use(function* (next) { |
4 |
// faça algo antes de esperar/passar para a próxima função gerador, que será o primeiro da ida
|
5 |
console.log("A"); |
6 |
yield next; |
7 |
|
8 |
// faça algo quando a execução voltar, esse será o último evento da volta
|
9 |
console.log("B"); |
10 |
});
|
11 |
|
12 |
koa.use(function* (next) { |
13 |
// faça algo antes de esperar/passar para a próxima função gerador, que será o segundo da ida
|
14 |
console.log("C"); |
15 |
|
16 |
yield next; |
17 |
|
18 |
// faça algo quando a execução voltar, esse será o segundo evento da volta
|
19 |
console.log("D"); |
20 |
});
|
21 |
|
22 |
koa.use(function* () { // faça algo antes de esperar/passar para a próxima função gerador, que será a última da ida |
23 |
console.log("E"); |
24 |
this.body = "hey guys"; |
25 |
console.log("F"); // Primeiro evento da volta (do último para o primeiro) |
26 |
|
27 |
});
|
28 |
|
29 |
koa.listen(3000); |
O código acima é bem simples. Note que que nem todos as declarações de console.log
são requeridas mas elas ajudarão a clarear o entendimento do fluxo de execução de ida e volta do Koa.js.
Entendendo o Fluxo de Execução do Exemplo
Quando executamos essa aplicação e digitamos o endereço localhost:3000
no navegador, podemos observar que os console.logs
no terminal não estão na ordem A-B-C-D-E-F. Nem na ordem A-C-E-B-D-F.
A ordem á A-C-E-F-D-B que demonstra o comportamento de ida e volta dos yields
da execução em uma aplicação em Koa.
Talvez tenha notado que a sequência foi impressa duas vezes. Isso é devido à dupla requisição enviada pelo navegador, onde uma serve para buscar o favicon.
Dica: O método koa.use(function)
adiciona uma função mediadora à aplicação.
Em Conclusão
E isso é tudo para essa primeira parte deste tutorial sobre geradores no JavaScript e sobre o Koa.js. Você aprendeu sobre a maioria dos pré-requesitos, como o que são geradores, como usá-los, como usar uma submissão delegada e como o controle de fluxo funciona no Koa.js.
Na próxima parte deste tutorial, iremos mais a fundo no Koa e aprenderemos como construir uma aplicação CRUD. Se tiver quaisquer dúvidas ou comentários, sinta-se à vontade de contatar-me ou deixar uma mensagem logo abaixo.
Seja o primeiro a saber sobre novas traduções–siga @tutsplus_pt no Twitter!