Javascript - Criando um módulo Ajax com Promises - Parte 1
No artigo anterior, você viu como as Promises resolvem o problema de callback hell. Agora vamos ver na prática como criar nossas próprias Promises!
O que iremos fazer?
Nosso desafio é criar um módulo para usar Ajax, sem qualquer library ou framework, e que possamos obter os resultados das requisições via Promises.
O nosso módulo será feito usando a técnica de TDD, ou seja, primeiro criamos um teste com o resultado esperado, e então partimos para o código em si :)
E o nosso primeiro passo é criar a estrutura do nosso projeto!
Você pode acompanhar o andamento desse módulo através desse repositório no Github :D
O que dá pra fazer com Ajax?
Acho que o exemplo mais comum é o carrinho de compras com Ajax.
Estrutura do projeto
Execute o comando abaixo no seu terminal, em um diretório separado para o projeto:
1 | mkdir src tests && touch .editorconfig .jshintrc .gitignore gulpfile.js index.html src/ajax.js tests/test.ajax.js && echo "{}" > package.json |
Isso irá gerar a seguinte estrutura:
1 | . |
Com nosso projeto criado, vamos montar nosso ambiente de testes :D
Montando o ambiente de testes
Se você ainda não está habituado com testes, ou nunca escreveu um, ou ainda não sabe para o que realmente eles servem, é muito importante que você leia esse artigo antes de continuar :D
Vamos instalar os módulos do Gulp necessários para que possamos fazer os testes no nosso módulo:
1 | npm i --save-dev gulp gulp-mocha gulp-istanbul gulp-load-plugins chai |
Configurações dos arquivos
Nosso arquivo .jshintrc
ficará assim:
1 | { |
Já o .editorconfig
terá a seguinte configuração:
1 | root = true |
E o .gitignore
:
1 | node_modules/ |
E agora vamos configurar nosso gulpfile.js
:
1 | ; |
E Enfim, nosso ‘index.html’:
1 |
|
Acessando essa index.html
no seu navegador, você terá acesso à todos os testes, podendo acompanhá-los à medida em que forem sendo implementados :)
Detalhes do método
Antes de darmos início, nós precisamos definir o que precisa ser implementado no nosso módulo. Nessa etapa, não vamos definir código, mas sim como ele deve funcionar.
Basicamente, nós queremos que nosso módulo utilize Ajax (XMLHttpRequest), e que ele responda aos métodos get
, post
, put
e delete
.
A resposta deve vir no formato de Promises, com os métodos done
e error
.
Esse será nosso MVP.
Já pode colocar o Gulp pra rodar e ficar assistindo nossos arquivos, com o comando:
1 | gulp |
Usando o padrão UMD
Para que nosso módulo funcione corretamente com CommonJS, AMD ou sem nenhum padrão de módulos específico, precisamos usar o formato UMD.
Nosso módulo src/ajax.js
iniciará com a seguinte estrutura:
1 | ;(function ( root, factory ) { |
Das linhas 1
a 13
, aplicamos o UMD. Agora nosso módulo é Universal :D
O comentário na linha 3
, é para que o Istanbul ignore esse if
, pois não teremos os 3
módulos juntos (AMD, CommonJS e sem nenhum), será somente um desses, então não temos como fazer com que toda essa parte seja coberta por testes. Logo, podemos ignorá-la.
Observação importante:
Se você tentar incluir esse módulo em qualquer um dos 3 formatos citados acima, vai ver que ele vai funcionar. Quando você não consegue dar cobertura a um código, como é o caso do UMD, você precisa, ao menos, garantir manualmente que tudo funciona. Não adianta comentar todo o código para que o Istanbul ignore, pois você estará enganando a si mesmo. Use essa feature com cautela.
Iniciando os testes
Agora sim estamos prontos para começar a codar! Nossa primeira asserção irá testar a interface do nosso módulo. Precisamos garantir que nosso módulo tenha os métodos get
, post
, put
e delete
.
Vamos então criar o teste para isso. A base do nosso arquivo tests/test.ajax.js
ficará assim:
1 | ;(function ( root, factory ) { |
Vamos adicionar o UMD também para o nosso teste, pois ele ficará rodando no terminal, com Node. Assim nós poderemos acompanhar os resultados tanto no browser, como no terminal :)
Incluímos a biblioteca Chai, para fazer as asserções dos nossos testes.
Na linha 18
, damos início ao teste:
O describe
vai criar um wrapper
com vários testes de uma parte específica do módulo. Nesse primeiro describe
, vamos testar a interface do módulo.
Nosso primeiro teste, na linha 19
, diz que nosso módulo “Deveria ter um método chamado get“.
Instanciamos o objeto do nosso módulo - new Ajax()
- e fazemos a asserção, verificando se a propriedade get
existe.
E o nosso teste quebra, pois esse método não existe:
E esse é exatamente o comportamento esperado, pois ainda não temos código no nosso módulo que o faça funcionar! Esse é o primeiro passo do TDD: O RED.
Agora, você lembra qual o próximo passo? Após nosso teste quebrar, pois adicionamos um teste para verificar algo que ainda não existe, vamos tentar fazer o teste passar, com o mínimo de código possível (baby steps):
Adicionamos então ao nosso arquivo src/ajax.js
:
1 | ... |
Pronto, agora temos um método get
! Vamos ver se nosso teste passou?
Agora sim! Temos o GREEN, pois nosso teste passou.
Podemos ainda acompanhar no terminal como está a cobertura do nosso código:
Como estamos usando TDD, a tendência é que tenhamos sempre 100% do nosso código coberto por testes! :D
O próximo passo é o BLUE, ou Refactory. Nesse caso, não precisamos refatorar nosso código, pois não tem nada a ser refatorado.
Com o passar dos testes, dependendo do baby step que nós utilizarmos, precisaremos refatorar o código para que ele se mantenha em ordem. O passo do refactory serve somente para limpar o código já existente. Você nunca deve incluir nenhuma funcionalidade a mais no momento do refactory. Os testes que passam devem continuar passando, mas a leitura do código deve ser melhor do que você deixou da última vez :)
Curioso para ver como isso continua? Então aguarde o próximo post! :D
Fica como lição de casa pra você fazer os outros 3 testes com os métodos post
, put
e delete
!
Nos próximos artigos, vamos continuar criando nosso módulo, até que ele resolva nosso primeiro objetivo: ter os 4 métodos e responder com as Promises.
Ficou com dúvidas? Comentae!
Até lá!
Sobre o #1postperday: https://blog.da2k.com.br/2014/12/31/um-post-por-dia/
Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: https://github.com/fdaciuk/fdaciuk.github.io/issues/1