<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Da2k Blog</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://blog.da2k.com.br/"/>
  <updated>2025-05-12T12:40:00.854Z</updated>
  <id>https://blog.da2k.com.br/</id>
  
  <author>
    <name>Fernando Daciuk</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>EcmaScript Modules: Módulos nativos no JavaScript</title>
    <link href="https://blog.da2k.com.br/2019/02/25/ecmascript-modules-modulos-nativos-no-javascript/"/>
    <id>https://blog.da2k.com.br/2019/02/25/ecmascript-modules-modulos-nativos-no-javascript/</id>
    <published>2019-02-25T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.854Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/uploads/2019/02/ecma-script-modules.png" alt=""></p><p>Já falamos sobre várias formas de utilizar módulos no JavaScript aqui no blog, usando <a href="/2015/01/03/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-1-3/">AMD</a>, <a href="https://blog.da2k.com.br/2015/01/04/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-2-3/">CommonJS</a> e <a href="https://blog.da2k.com.br/2015/01/05/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-3-3/">UMD</a>.</p><p>Mas agora o JavaScript tem suporte a módulos nativos! Quer aprender como utlizar? Vem comigo =)</p><a id="more"></a><h2 id="O-que-sao-EcmaScript-Modules"><a href="#O-que-sao-EcmaScript-Modules" class="headerlink" title="O que são EcmaScript Modules?"></a>O que são EcmaScript Modules?</h2><p>EcmaScript é o que podemos chamar de “a documentação da linguagem JavaScript”.<br>É o lugar onde é definido como as coisas devem funcionar na linguagem.</p><p>Você já deve ter lido alguns posts aqui do blog, onde eu falo sobre meus <em>workflows</em> para trabalhar como módulos no JavaScript. Se ainda não leu, pode ler <a href="/2015/02/13/escalando-javascript-no-browser/">aqui</a>, <a href="/2015/01/18/requirejs-carregando-javacript-sob-demanda/">aqui</a> e <a href="/2014/03/18/meu-workflow-javascript-com-module-pattern/">aqui</a>.</p><p>Se você perceber, não existia uma forma padrão de criar módulos em JS sem passar a informação pelo escopo global.</p><p>Usávamos técnicas como IIFE, AMD, CommonJS (Node), UMD… tudo para tentar modularizar nossas aplicações, e não deixar o código virar um espaguete em arquivos com 4k linhas de código.</p><p>Então surgiu essa nova especificação para salvar nossas vidas: <strong>EcmaScript Modules</strong> (ou <strong>ES Modules</strong>, para os mais chegados).</p><p>E a ideia dessa especificação é exatamente o que o seu nome diz: permitir a modularização dos nossos códigos JS, sem precisar passar pelo escopo global :D</p><p>Da hora, não!?</p><p>Vamos ver como ela funciona? Vem comigo!</p><h2 id="Strict"><a href="#Strict" class="headerlink" title="Strict"></a>Strict</h2><p>Já vou começar falando que não precisamos mais usar a diretiva <code>&#39;use strict&#39;</code>: ES Modules são <em>strict</em> por padrão!</p><h2 id="Como-funcionam-os-ES-Modules"><a href="#Como-funcionam-os-ES-Modules" class="headerlink" title="Como funcionam os ES Modules?"></a>Como funcionam os ES Modules?</h2><p>Vamos ver na prática como é o funcionamento dos módulos! Eles ainda não estão implementados totalmente no Node.js, mas na versão mais recente do Chrome você já consegue usá-los!</p><p>Obs.: Não testei em outros navegadores, mas <a href="https://caniuse.com/#feat=es6-module" target="_blank" rel="noopener">aqui</a> você consegue ver o suporte atual dessa feature.</p><p>A primeira coisa a fazer é criar um arquivo <code>index.html</code>, onde iremos testar nosso código. Vamos criar uma estrutura básica:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">title</span>&gt;</span>ES Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Testando ES Modules<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"module"</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript">    <span class="built_in">console</span>.log(<span class="string">'this:'</span>, <span class="keyword">this</span>)</span></span><br><span class="line"><span class="undefined">  </span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>Essa é uma estrutura padrão de uma página em HTML5, com um pequeno detalhe: perceba que a tag <code>script</code> tem um <code>type=&quot;module&quot;</code>. Isso faz o browser “ativar” a feature de módulo, e todo o código escrito ali dentro dessa tag script é reconhecido como um módulo.</p><p>Lembrando que ES Modules são <em>strict</em> por padrão: veja que, ainda que não façamos uso da diretiva <code>&#39;use strict&#39;</code>, o resultado de <code>this</code> será <code>undefined</code> no exemplo acima, e não o objeto global <code>window</code> =)</p><p>E como boa prática, para separar o código JS do documento HTML, usamos a mesma ideia de sempre: uma tag <code>script</code> com o atributo <code>src</code>, mas com a adição do <code>type=&quot;module&quot;</code>:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">title</span>&gt;</span>ES Modules<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Testando ES Modules<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"module"</span> <span class="attr">src</span>=<span class="string">"./main.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>E só colocamos no arquivo <code>main.js</code> o console.log que estava na index.html:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">'this:'</span>, <span class="keyword">this</span>)</span><br></pre></td></tr></table></figure><p>Só tem um pequeno problema: ao tentar abrir esse arquivo apenas clicando duas vezes nele, ele será aberto no navegador usando o protocolo <code>file://</code>. E por se tratar de um módulo, o navegador não permite acessá-lo dentro de uma página web sem ser via o protocolo HTTP, dentro da mesma origem (mesmo domínio), devolvendo no console um erro de CORS:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">index.html:1 Access to script at &apos;file:///media/storage/code/test-es-modules-browser/02/main.js&apos; from origin &apos;null&apos; has been blocked by CORS policy: The response is invalid.</span><br><span class="line">index.html:9 GET file:///media/storage/code/test-es-modules-browser/02/main.js net::ERR_FAILED</span><br></pre></td></tr></table></figure><p>Pra resolver isso, é preciso executar o index.html à partir de um servidor HTTP.</p><p>Vamos usar o <code>http-server</code>.</p><p>E pra facilitar nossa vida, se você tiver a última versão do Node.js instalado na sua máquina, você deve ter também, além do NPM, uma ferramenta chamada <code>npx</code>, que permite usar módulos globais sem instalação. Para usar o <code>http-server</code> à partir do <code>npx</code>, acesse o diretório onde você criou os arquivos <code>index.html</code> e <code>main.js</code>, e execute o comando:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx http-server -c-1</span><br></pre></td></tr></table></figure><p>Esse comando vai servir o <code>index.html</code> no endereço <code>http://localhost:8080</code>. Acesse esse endereço no seu navegador, e a mensagem que estava aparecendo no console deve estar sendeo exibida corretamente =)<br>Detalhe: o <code>-c-1</code> ao final do comando é apenas para não deixar o <code>http-server</code> fazer cache, e evitar problemas conhecidos haha :D</p><p>Agora podemos voltar ao assunto :P</p><p><em>Ok, mas qual a utilidade de ter módulos?</em></p><p>Basicamente duas:</p><ul><li>A possibilidade de quebrar arquivos gigantes em arquivos menores, com responsabilidades melhor definidas;</li><li>Reutilização de código, já que poderemos isolar conforme a necessidade.</li></ul><p>Vamos começar com um exemplo simples: uma função de soma. Crie um arquivo chamado <code>sum.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sum</span> (<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Agora, para que possamos utilizar esse módulo, ele precisa estar disponível para ser importado, lembrando que módulos têm um escopo próprio, e não são compartilhados no escopo global.</p><p>Para fazer isso, temos algumas formas. Vamos aprender e analisar cada uma delas:</p><h3 id="Export-default-Exportando-a-referencia-da-funcao"><a href="#Export-default-Exportando-a-referencia-da-funcao" class="headerlink" title="Export default: Exportando a referência da função"></a>Export default: Exportando a referência da função</h3><p>A maneira mais simples de exportar a função é usando a seguinte expressão no final do arquivo <code>sum.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> sum</span><br></pre></td></tr></table></figure><p>Isso irá exportar a função de forma “default”. Vamos falar sobre o que isso significa em breve.</p><p>Agora, para que possamos importar e usar essa função, podemos adicionar, no início do nosso arquivo <code>main.js</code>, a seguinte expressão:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sum <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br></pre></td></tr></table></figure><p>Dessa forma, estamos importando a função que foi exportada como “default” do arquivo <code>sum.js</code>, atribuindo o valor exportado à uma variável nomeada <code>sum</code>.</p><p>Podemos usar qualquer nome para importar um valor que foi exportado como “default”:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> arroz <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br></pre></td></tr></table></figure><p>Isso faz com que com que a variável <code>arroz</code> seja criada e receba a referência da função <code>sum</code>, que foi exportada do arquivo <code>sum.js</code> :)</p><p>Voltando ao exemplo, vamos tentar agora usar a função <code>sum</code>, importada no arquivo <code>main.js</code>. Logo após a chamada de “import” da função <code>sum</code>, adicione o código:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>))</span><br></pre></td></tr></table></figure><p>Ao atualizar a página, você verá no console o valor <code>3</code> :)</p><p>Como você pode perceber, quando usamos <code>export default</code> não precisamos, necessariamente, dar um nome ao valor exportado, pois ele pode ser importado com qualquer nome.</p><p>Então temos a opção de exportar diretamente uma função (nomeada ou não) do arquivo <code>sum.js</code>, dessa forma:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> <span class="title">sum</span> (<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Veja que agora, no arquivo <code>sum.js</code>, apenas tiramos o <code>export default sum</code> do final do arquivo, e exportamos diretamente a função, dessa forma em forma de expressão, como função nomeada, não como uma função literal.</p><p>Se podemos usar a função como expressão, o nome dela é opcional. O código abaixo também funciona corretamente:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="function"><span class="keyword">function</span> (<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Veja que a expressão da função foi exportada sem um nome =)</p><p>Pra reduzir ainda mais esse código, é possível exportar uma <em>arrow function</em>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (a, b) =&gt; a + b</span><br></pre></td></tr></table></figure><p>Se você não entende a sintaxe de uma arrow function, eu escrevi sobre o assunto <a href="/2019/01/07/javascript-tudo-sobre-arrow-functions/">aqui</a></p><p>E isso vale para qualquer tipo de dado (funções, strings, objetos, arrays, promises, etc).</p><h3 id="Export-nomeado"><a href="#Export-nomeado" class="headerlink" title="Export nomeado"></a>Export nomeado</h3><p>Podemos também exportar de forma nomeada, forçando assim a obrigatoriedade de um nome específico na hora de importar o módulo.</p><p>Vamos alterar o tipo de exportação do módulo <code>sum.js</code>. Primeiro, vamos separar novamente a criação da função, e a linha que faz a exportação:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> sum</span><br></pre></td></tr></table></figure><p>No código acima, só criamos uma variável <code>sum</code>, e atribuímos a ela a função, e então exportamos essa função.</p><p>Para usarmos o export nomeado, nosso código deve ficar assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> &#123; sum &#125;</span><br></pre></td></tr></table></figure><p>Perceba que simplesmente trocamos a palavra <code>default</code> por chaves, e colocamos o nome que será exportado entre as chaves. Só como adendo: essas chaves <strong>não</strong> são chaves de criação de um novo objeto, ok? É outra sintaxe =)</p><p>Se você executar o código como está, você deve ver o seguinte erro no console:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Uncaught SyntaxError: The requested module &apos;./sum.js&apos; does not provide an export named &apos;default&apos;</span><br></pre></td></tr></table></figure><p>Isso porque não fizemos nenhuma exportação “default” no nosso módulo, temos apenas um export nomeado.</p><p><em>Beleza, mas então como importamos um módulo que foi exportado de forma nomeada?</em></p><p>Bem simples! No arquivo <code>main.js</code>, apenas envolva a palavra <code>sum</code>, que foi usada como variável que recebe o módulo, entre chaves:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; sum &#125; <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br></pre></td></tr></table></figure><p>Veja que o negócio segue um padrão: quando você exporta um módulo com <code>default</code>, você pode dar qualquer nome na hora de importar. Já se exportar de forma nomeada, na hora da importação é sempre necessário usar o <strong>mesmo nome</strong> que foi usado para exportar.</p><p>Podemos ainda exportar a função <code>sum</code> de forma nomeada na mesma linha, apenas fazendo assim no arquivo <code>sum.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br></pre></td></tr></table></figure><p>O interpretador da linguagem vai entender o nome da variável - ou o nome da função, quando usado uma função nomeada - como o nome a ser exportado. Bem legal né? =)</p><p>Agora, vamos ver o que acontece se, na hora de importar o módulo, usarmos um nome diferente do que foi exportado. No arquivo <code>main.js</code>, vamos trocar <code>sum</code> por <code>arroz</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; arroz &#125; <span class="keyword">from</span> <span class="string">'./sum'</span></span><br></pre></td></tr></table></figure><p>Obviamente recebemos um erro:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Uncaught SyntaxError: The requested module &apos;./sum.js&apos; does not provide an export named &apos;arroz&apos;</span><br></pre></td></tr></table></figure><p><em>Mas e se eu quisesse usar mesmo <code>arroz</code> ao invés de <code>sum</code>, é possível?</em></p><p>Sim! E não só é possível renomear um módulo que foi exportado com um nome, como é bem simples, veja só. Ainda no arquivo <code>main.js</code>, vamos fazer nosso módulo funcionar com o nome <code>arroz</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; sum <span class="keyword">as</span> arroz &#125; <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(arroz(<span class="number">1</span>, <span class="number">2</span>))</span><br></pre></td></tr></table></figure><p>Veja que simples: só precisamos usar a palavra <code>as</code> (como), ou seja: “importe <code>sum</code> como <code>arroz</code> lá do arquivo <code>./sum.js</code>“ :D</p><p>Simples não? =)</p><p>Podemos usar a mesma ideia para renomear um export nomeado! Vamos voltar ao arquivo <code>sum.js</code>. Ele estava assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br></pre></td></tr></table></figure><p>Agora vamos exportar <code>sum</code> com o nome <code>plus</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> &#123; sum <span class="keyword">as</span> plus &#125;</span><br></pre></td></tr></table></figure><p>Lembra que eu falei que as chaves no <code>export</code> não eram de um objeto? Então.. essa é a sintaxe para renomear uma exportação. É como se disséssemos: “Exporte <code>sum</code> como <code>plus</code>“ =)</p><p>E agora só temos que fazer a importação correta do nome <code>plus</code> no arquivo <code>main.js</code> para tudo voltar a funcionar:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; plus &#125; <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(plus(<span class="number">1</span>, <span class="number">2</span>))</span><br></pre></td></tr></table></figure><p>Pronto! =)</p><p>Uma coisa interessante de notar: lembra do erro quando nós exportamos a função <code>sum</code> de forma nomeada, mas tentamos importar como <code>default</code> (sem usar as chaves)? O erro foi o seguinte:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Uncaught SyntaxError: The requested module &apos;./sum.js&apos; does not provide an export named &apos;default&apos;</span><br></pre></td></tr></table></figure><p>Veja a dica: o erro diz que o módulo <code>sum.js</code> não proveu um export nomeado como “default”.</p><p>Isso significa que podemos fazer algumas mandingas, do tipo:</p><p>No arquivo <code>sum.js</code>, exportamos a função como “default”:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> sum</span><br></pre></td></tr></table></figure><p>E no arquivo <code>main.js</code>, fazemos a mandinga:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="keyword">default</span> <span class="keyword">as</span> plus &#125; <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(plus(<span class="number">1</span>, <span class="number">2</span>))</span><br></pre></td></tr></table></figure><p>Veja que <code>default</code> pode ser usado como um nome para renomear o módulo! Claro que seria muito mais simples fazer apenas:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> plus <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br></pre></td></tr></table></figure><p>Mas o exemplo foi só pra você entender que isso também é possível, e pode ajudar em alguns casos que veremos mais adiante =)</p><p>Como você já deve imaginar, podemos fazer também o processo inverso: renomear um módulo para ser exportado como <code>default</code>, dessa forma (no arquivo <code>sum.js</code>):</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> &#123; sum <span class="keyword">as</span> <span class="keyword">default</span> &#125;</span><br></pre></td></tr></table></figure><h3 id="Exportando-mais-de-um-valor-por-modulo"><a href="#Exportando-mais-de-um-valor-por-modulo" class="headerlink" title="Exportando mais de um valor por módulo"></a>Exportando mais de um valor por módulo</h3><p>Para exportar mais de um valor por módulo, vamos criar um novo arquivo chamado <code>calculator.js</code>, e nesse arquivo vamos criar funções para as operações matemáticas mais comuns:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">const</span> sub = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a - b</span><br><span class="line"><span class="keyword">const</span> mult = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a * b</span><br><span class="line"><span class="keyword">const</span> div = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a / b</span><br></pre></td></tr></table></figure><p>Para exportar facilmente cada uma dessas funções, só precisamos usar a palavra chave <code>export</code> antes de cada declaração:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> sub = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a - b</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> mult = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a * b</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> div = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a / b</span><br></pre></td></tr></table></figure><p>Pronto!</p><p><em>Certo, mas como importar várias funções de uma única vez?</em></p><p>Simples: lá no nosso arquivo <code>main.js</code>, vamos importar essas funções de <code>calculator.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; sum, sub, mult, div &#125; <span class="keyword">from</span> <span class="string">'./calculator'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>)) <span class="comment">// 3</span></span><br><span class="line"><span class="built_in">console</span>.log(sub(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">console</span>.log(mult(<span class="number">3</span>, <span class="number">4</span>)) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">console</span>.log(div(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 5</span></span><br></pre></td></tr></table></figure><p>Show! Ainda tem a segunda forma de exportar lá do <code>calculator.js</code>. Podemos fazer assim também:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">const</span> sub = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a - b</span><br><span class="line"><span class="keyword">const</span> mult = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a * b</span><br><span class="line"><span class="keyword">const</span> div = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a / b</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> &#123; sum, sub, mult, div &#125;</span><br></pre></td></tr></table></figure><p>Que funciona do mesmo jeito. Escolha o que fica melhor para o seu caso e use :D</p><h3 id="Importando-varios-modulos-nomeados-de-uma-so-vez"><a href="#Importando-varios-modulos-nomeados-de-uma-so-vez" class="headerlink" title="Importando vários módulos nomeados de uma só vez"></a>Importando vários módulos nomeados de uma só vez</h3><p>No último exemplo, importamos vários módulos em uma só chamada. Mas é possível também importar todos os módulos que foram exportados de forma nomeada, usando o operador especial <code>*</code>, olha só (no <code>main.js</code>):</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> * <span class="keyword">as</span> calculator <span class="keyword">from</span> <span class="string">'./calculator.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(calculator.sum(<span class="number">1</span>, <span class="number">2</span>)) <span class="comment">// 3</span></span><br><span class="line"><span class="built_in">console</span>.log(calculator.sub(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">console</span>.log(calculator.mult(<span class="number">3</span>, <span class="number">4</span>)) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">console</span>.log(calculator.div(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 5</span></span><br></pre></td></tr></table></figure><p>Dessa forma nós importamos todos os valores que foram exportados com um nome em <code>calculator.js</code>, e atribuímos esses valores como propriedades de um objeto que chamamos de <code>calculator</code>.</p><p><em>E se tivéssemos algum valor exportado de forma <code>default</code> no <code>calculator.js</code>?</em></p><p>Vamos ver como ficaria esse caso. Agora o arquivo <code>calculator.js</code> deve ficar assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br><span class="line"><span class="keyword">const</span> sub = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a - b</span><br><span class="line"><span class="keyword">const</span> mult = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a * b</span><br><span class="line"><span class="keyword">const</span> div = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a / b</span><br><span class="line"><span class="keyword">const</span> obj = &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> &#123; sum, sub, mult, div &#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> obj</span><br></pre></td></tr></table></figure><p>Veja que criamos uma variável <code>obj</code> e exportamos essa variável com o <code>default</code>. Para ter acesso a esse objeto no <code>main.js</code>, onde foi usado o <code>*</code> para importar todos os módulos, podemos usar <code>calculator.default</code>, já que esse objeto foi exportado como <code>default</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(calculator.default) <span class="comment">// &#123;&#125;</span></span><br></pre></td></tr></table></figure><p>Lembre-se que o <code>export default</code> pode ser exportado de duas formas:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> obj</span><br></pre></td></tr></table></figure><p>Ou ainda, usando a forma nomeada:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> &#123; obj <span class="keyword">as</span> <span class="keyword">default</span> &#125;</span><br></pre></td></tr></table></figure><p>Por isso conseguimos pegar esse valor quando importado usando o <code>*</code> :)</p><p>Nesse último exemplo do arquivo <code>calculator.js</code>, é importante frisar que só podemos ter um único módulo exportado como <code>default</code>, por motivos óbvios =)</p><p>Mas se não estiver tão claro, é só pensar no seguinte: o nome <code>default</code> pode ser usado como um “nome” na hora de importar. Se você tiver dois <code>export default</code>, qual deles deveria ser usado com o nome <code>default</code>, na hora de importar?</p><p>Deu pra entender a ideia? Sempre que você precisar exportar um só valor, pode usar tanto o <code>default</code> como o formato nomeado. Mas se for exportar mais de um valor, use o formato nomeado.</p><p>O <code>default</code> não é obrigatório, e muitas vezes desencorajado por algumas pessoas da comunidade, com a alegação de que exports nomeados podem ser melhor “padronizados” já que eles precisam ter o nome exato na hora de importar.</p><p>Exemplo: você vai importar o jQuery na sua aplicação. Se ele fosse exportado de forma <code>default</code>, você poderia usar em um arquivo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> jQuery <span class="keyword">from</span> <span class="string">'./jquery.min.js'</span></span><br></pre></td></tr></table></figure><p>Em outro arquivo, poderia usar:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> jQ <span class="keyword">from</span> <span class="string">'./jquery.min.js'</span></span><br></pre></td></tr></table></figure><p>E assim por diante. Agora, se o export for nomeado, você é forçado a usar o nome que foi usado para exportar - tudo bem que dá  pra renomear, mas ainda assim fica muito mais explícito =)</p><p>Acho que deu pra entender :)</p><h3 id="Importar-o-default-separado-dos-nomeados"><a href="#Importar-o-default-separado-dos-nomeados" class="headerlink" title="Importar o default separado dos nomeados"></a>Importar o default separado dos nomeados</h3><p>Também é possível fazer o import do valor default de forma separada dos nomeados, mas ainda na mesma chamada, veja o que vamos fazer no arquivo <code>main.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> calc, &#123; sum, sub, mult, div &#125; <span class="keyword">from</span> <span class="string">'./calculator.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>)) <span class="comment">// 3</span></span><br><span class="line"><span class="built_in">console</span>.log(sub(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">console</span>.log(mult(<span class="number">3</span>, <span class="number">4</span>)) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">console</span>.log(div(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 5</span></span><br><span class="line"><span class="built_in">console</span>.log(calc) <span class="comment">// &#123;&#125;</span></span><br></pre></td></tr></table></figure><p>Veja que <code>calc</code> fica fora dos parênteses, pois é o nome dado ao valor que foi exportado com <code>default</code> :)</p><h3 id="Exportar-importando"><a href="#Exportar-importando" class="headerlink" title="Exportar importando"></a>Exportar importando</h3><p>Ainda tem uma outra feature interessante, onde você pode exportar um módulo, fazendo a importação desse na mesma sentença. Vamos fazer o seguinte: vamos criar um arquivo para cada operação matemática: <code>sum.js</code>, <code>sub.js</code>, <code>mult.js</code> e <code>div.js</code>.</p><p>Ao fazer isso, vamos mover cada função que está em <code>calculator.js</code> para o seu respectivo arquivo, e exportar de forma <code>default</code> em cada um.</p><p>Depois, só precisamos importar tudo no arquivo <code>calculator.js</code>, e então exportar. Mas podemos fazer ainda melhor, saca só:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> &#123; <span class="keyword">default</span> <span class="keyword">as</span> sum &#125; <span class="keyword">from</span> <span class="string">'./sum.js'</span></span><br><span class="line"><span class="keyword">export</span> &#123; <span class="keyword">default</span> <span class="keyword">as</span> sub &#125; <span class="keyword">from</span> <span class="string">'./sub.js'</span></span><br><span class="line"><span class="keyword">export</span> &#123; <span class="keyword">default</span> <span class="keyword">as</span> mult &#125; <span class="keyword">from</span> <span class="string">'./mult.js'</span></span><br><span class="line"><span class="keyword">export</span> &#123; <span class="keyword">default</span> <span class="keyword">as</span> div &#125; <span class="keyword">from</span> <span class="string">'./div.js'</span></span><br></pre></td></tr></table></figure><p>Veja que usamos a sintaxe <code>export from</code>, que, basicamente, importa o módulo que foi exportado como <code>default</code> do seu arquivo setado após o <code>from</code>, nomeia esse módulo e faz o <code>export</code> dele à partir do arquivo <code>calculator.js</code>.</p><p>Assim, podemos fazer a importação nomeada de qualquer um desses módulos direto do <code>calculator.js</code> no <code>main.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; sum, sub, mult, div &#125; <span class="keyword">from</span> <span class="string">'./calculator.js'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>)) <span class="comment">// 3</span></span><br><span class="line"><span class="built_in">console</span>.log(sub(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">console</span>.log(mult(<span class="number">3</span>, <span class="number">4</span>)) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">console</span>.log(div(<span class="number">10</span>, <span class="number">2</span>)) <span class="comment">// 5</span></span><br></pre></td></tr></table></figure><p>Da hora não? Isso é bem legal pra quando precisamos separar os nossos módulos, mas ainda assim queremos uma melhor organização, fazendo o import à partir de um único módulo central =)</p><hr><p>É importante dizer também que esse sistema de módulos é <strong>estático</strong>. Significa que não podemos, por exemplo, importar arquivos à partir de um nome dinâmico.</p><p>Vou exemplificar: imagine que você tem os seguintes arquivos: <code>mod1.js</code>, <code>mod2.js</code>, <code>mod3.js</code>.</p><p>Você poderia pensar: <em>eu tenho um padrão no nome dos meus arquivos. Talvez eu possa fazer um loop e importá-los todos de uma só vez, não?</em></p><p><strong>NÃO!</strong></p><p>Não dá pra fazer algo assim, por exemplo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arrayDe1A3 = <span class="built_in">Array</span>.from(&#123; <span class="attr">length</span>: <span class="number">3</span> &#125;, (_, i) =&gt; i + <span class="number">1</span>)</span><br><span class="line">arrayDe1A3.forEach(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">import</span> item <span class="keyword">from</span> <span class="string">`./mod<span class="subst">$&#123;item&#125;</span>.js`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>Uma porque eu acabei de falar que o import é estático :P</p><p>Outra que <code>item</code> seria o nome da variável atribuída para cada import.</p><p>E essa sintaxe não aceita nomes dinâmicos, como usado em <code>./mod${item}.js</code>. Ainda que usasse concatenação - algo assim: <code>import mod1 from &#39;mod&#39; + item</code>  - não funciona.</p><p>Depois do <code>from</code>, você só consegue usar aspas simples ou duplas, não dá pra usar <em>template literals</em> (as crases).</p><p>Por isso é importante que os seus <code>import</code> estejam sempre no início do seu arquivo. Nunca faça algo do tipo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sum <span class="keyword">from</span> <span class="string">'./sum'</span></span><br><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> sub <span class="keyword">from</span> <span class="string">'./sub'</span></span><br><span class="line"><span class="built_in">console</span>.log(sub(<span class="number">2</span>, <span class="number">1</span>))</span><br></pre></td></tr></table></figure><p>Apesar de funcionar, sempre faça todos os imports no início do arquivo, e só depois de todos os imports é que você pode usar os valores, ok? =)</p><h3 id="Modulos-dinamicos"><a href="#Modulos-dinamicos" class="headerlink" title="Módulos dinâmicos"></a>Módulos dinâmicos</h3><p>A sintaxe que eu acabei de apresentar é estática, mas com certeza tem alguns momentos em que precisamos importar um ou outro módulo sob demanda, e de forma dinâmica, afinal, precisamos de liberdade e performance =)</p><p>Para isso, existe uma especificação que está para entrar também nos ES Modules, para conseguirmos importar módulos de forma dinâmica: é a <strong>função</strong> <code>import()</code>.</p><p>Isso mesmo, uma função! Quando usamos <code>import()</code> como função, passando via parâmetro o caminho do módulo que queremos importar, ela nos retornará uma Promise.</p><p>E dessa vez, o nome do módulo pode ser passado de forma dinâmica, sem problemas. E esse import você pode usar onde quiser, inclusive de forma condicional (dentro de um <code>if</code>, por exemplo). :D</p><p>Vamos ver alguns exemplos.</p><p>Começaremos importando no <code>main.js</code> o <code>sum.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span>(<span class="string">'./sum.js'</span>).then(<span class="function">(<span class="params">sum</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'1 + 2 = '</span>, sum.default(<span class="number">1</span>, <span class="number">2</span>))</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>Lembre-se que o <code>import()</code> função sempre retorna uma Promise. Por isso precisamos usar o <code>.then</code> para saber quando essa Promise resolveu com o valor do nosso módulo.</p><p>Outro ponto interessante a levar em consideração: após resolver o módulo, sempre será retornado um objeto com todos os valores de forma nomeada. Como lá no módulo <code>sum.js</code> nós exportamos com <code>default</code> a função, aqui nós tivemos que usar <code>sum.default</code> para ter acesso à essa função =)</p><p>Como eu tinha dito anteriormente, com o <code>import()</code> função é possível usar nomes dinâmicos. Vamos fazer um teste no <code>main.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="built_in">module</span> = <span class="string">'sum'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span>(<span class="string">`./<span class="subst">$&#123;<span class="built_in">module</span>&#125;</span>.js`</span>).then(<span class="function">(<span class="params">sum</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'1 + 2 = '</span>, sum.default(<span class="number">1</span>, <span class="number">2</span>))</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>Veja que passamos o nome do módulo em uma variável <code>module</code>, e concatenamos com o <code>./</code> no início e o <code>.js</code> no final da chamada do nome do arquivo =)</p><p>Acho que com isso já dá pra se divertir bastante :D</p><hr><h3 id="Consideracoes-finais"><a href="#Consideracoes-finais" class="headerlink" title="Considerações finais"></a>Considerações finais</h3><p>Em algumas aplicações atuais, nós vemos import sem o <code>.js</code> no final, e até import de outros tipos de arquivos diferentes de <code>.js</code>, ou ainda a importação de módulos sem passar o <code>./</code> na frente, pra representar o caminho do arquivo.</p><p>É importante entender que os ES Modules servem apenas para arquivos JS, e não funcionam para importar imagens, markdown, svg, CSS, ou qualquer outro tipo de arquivo.</p><p>O que acontece nas aplicações usando libs e frameworks como React, Vue, Angular, etc., é que existe uma ferramenta por trás interceptando esses imports, e transformando esse código antes de ele, de fato, chegar no interpretador do navegador.</p><p>Por causa dessas configurações nessas ferramentas - como webpack, parcel, etc - é que conseguimos importar outros tipos de arquivos, mas isso não é o padrão dos ES Modules, ok? É importante estar ciente disso =)</p><hr><p>Bom, o artigo ficou bastante extenso, mas acho que eu consegui cobrir, se não tudo, ao menos as partes mais importantes quando se trata de módulos nativos no JS.</p><p>Gostou do artigo? Esqueci de algo? Me deixe saber nos comentários, e compartilhe esse post para que mais pessoas aprendam a usar essa feature maravilhosa da nossa amada liguagem &lt;3</p><p>Até o próximo artigo :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/uploads/2019/02/ecma-script-modules.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Já falamos sobre várias formas de utilizar módulos no JavaScript aqui no blog, usando &lt;a href=&quot;/2015/01/03/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-1-3/&quot;&gt;AMD&lt;/a&gt;, &lt;a href=&quot;https://blog.da2k.com.br/2015/01/04/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-2-3/&quot;&gt;CommonJS&lt;/a&gt; e &lt;a href=&quot;https://blog.da2k.com.br/2015/01/05/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-3-3/&quot;&gt;UMD&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Mas agora o JavaScript tem suporte a módulos nativos! Quer aprender como utlizar? Vem comigo =)&lt;/p&gt;
    
    </summary>
    
      <category term="modules" scheme="https://blog.da2k.com.br/categories/modules/"/>
    
    
  </entry>
  
  <entry>
    <title>JavaScript: Tudo sobre arrow functions</title>
    <link href="https://blog.da2k.com.br/2019/01/07/javascript-tudo-sobre-arrow-functions/"/>
    <id>https://blog.da2k.com.br/2019/01/07/javascript-tudo-sobre-arrow-functions/</id>
    <published>2019-01-07T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.866Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/uploads/2019/01/arrow-functions.png" alt=""></p><p>Apesar de ser uma <em>feature</em> bastante usada hoje em dia, algumas pessoas ainda não conhecem alguns segredos dessa nova sintaxe de funções em JavaScript.<br>Quer saber tudo o que as <em>arrow functions</em> são capazes de fazer? Vem comigo que eu te mostro =)</p><a id="more"></a><h2 id="Nova-sintaxe"><a href="#Nova-sintaxe" class="headerlink" title="Nova sintaxe"></a>Nova sintaxe</h2><p>Pra quem ainda não teve contato com as <em>arrow functions</em>, Vamos começar entendendo a nova sintaxe.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>À primeira vista pode parecer estranho, mas usando <code>function</code> tradicional, podemos obter o mesmo resultado assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function"><span class="keyword">function</span> (<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Acho que assim fica mais fácil de entender =)</p><p>A criação de uma <em>arrow function</em> consistem em 3 “passos”:</p><ul><li>Os parênteses, que é por onde a função recebe os argumentos (assim como na <code>function</code> tradicional);</li><li>A “seta” <code>=&gt;</code> - responsável pelo nome “arrow” function;</li><li>E as chaves: o bloco de código que representa o corpo da função.</li></ul><p>Perceba que a ideia é bastante similar à forma padrão de usar funções em JS, com a diferença que não usamos a palavra chave <code>function</code>, e sim uma seta (<code>=&gt;</code>) entre os parênteses (argumentos) e as chaves (bloco que gera o corpo da função).</p><p>Perceba também que nós usamos a <em>arrow function</em> como uma <strong>expressão</strong> - no caso, atribuindo o resultado da criação da <em>arrow function</em> à uma variável.</p><p>Diferente das <code>function</code> tradicionais, não existe uma forma literal de escrever uma <em>arrow- function</em>. Ela sempre deve ser usada como uma <strong>expressão</strong>.</p><p>Também não é possível nomear uma <em>arrow function</em>. Elas são sempre <strong>anônimas</strong>.</p><p>E para executar a função, nada muda:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(sum(<span class="number">1</span>, <span class="number">2</span>)) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure><h3 id="Variacoes-da-sintaxe"><a href="#Variacoes-da-sintaxe" class="headerlink" title="Variações da sintaxe"></a>Variações da sintaxe</h3><p><em>Arrow functions</em> permitem algumas variações, para deixar o código ainda mais enxuto. Vamos ver alguns exemplos:</p><p><strong>1) Função que não tem nada no seu corpo além do retorno</strong></p><p>Se a função vai apenas retornar algum valor, nós podemos omitir as chaves (corpo da função) e a palavra chave <code>return</code>.</p><p>Ao invés de escrever:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> a + b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Podemos apenas escrever:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span></span><br><span class="line">  a + b</span><br></pre></td></tr></table></figure><p>O resultado é o mesmo! E não há problema algum em quebrar linha após a “seta”, pois diferente do <code>return</code>, aqui não se aplica o <a href="http://www.bradoncode.com/blog/2015/08/26/javascript-semi-colon-insertion/" target="_blank" rel="noopener">ASI</a> (<em>Automatic Semicolon Insertion</em>, ou Inserção Automática do Ponto-e-Vírgula).</p><p>Pra deixa ainda mais simples, podemos colocar tudo em uma linha só:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> sum = <span class="function">(<span class="params">a, b</span>) =&gt;</span> a + b</span><br></pre></td></tr></table></figure><p>Para esse exemplo, o retorno da função fica implícito. Tudo o que está sendo colocado logo após a “seta” será considerado o retorno da função =)</p><p><strong>ATENÇÃO</strong></p><p>No exemplo acima, nós estamos retornando apenas a soma de dois números. Essa sintaxe é válida para qualquer tipo de dado sendo retornado <strong>exceto para objetos</strong>.</p><p><em>Por que objetos são uma exceção?</em></p><p>Para criarmos objetos literais, nós usamos as chaves. Logo, ao retornar um objeto, a criação da função teria um sentido ambíguo: <em>as chaves são para abrir o bloco do corpo da função, ou é um retorno de objeto literal?</em></p><p>Para esse caso específico, sempre que quisermos retornar um objeto de forma implítica usando uma <em>arrow function</em>, nós precisamos envolver esse objeto em parênteses.</p><p>Vamos ver alguns exemplos.</p><p>Para retornar um objeto de forma <strong>explícita</strong> (com o corpo da função, e o <code>return</code>), nós faríamos assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> person = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    name: <span class="string">'John'</span>,</span><br><span class="line">    surname: <span class="string">'Doe'</span>,</span><br><span class="line">    age: <span class="number">30</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Agora, se retornar de forma <strong>implícita</strong>, teríamos que fazer da seguinte forma:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> person = <span class="function"><span class="params">()</span> =&gt;</span> (&#123;</span><br><span class="line">  name: <span class="string">'John'</span>,</span><br><span class="line">  surname: <span class="string">'Doe'</span>,</span><br><span class="line">  age: <span class="number">30</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>Veja que a diferença foi apenas envolver o objeto em parênteses.</p><p>Em JS, os parênteses servem apenas para dar prioridade na execução de alguma expressão, então basicamente o que acontece é que toda a expressão dentro dos parênteses é que será retornada pela função <code>person</code>, assim que ela for executada. Fique muito atenta(o) a isso =)</p><p><strong>2) Funções com apenas um argumento</strong></p><p>Quando a função recebe apenas um argumento, podemos omitir os parênteses.</p><p>Então essa função:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> plusOne = <span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> value + <span class="number">1</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Poderia ser escrita com retorno implícito:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> plusOne = <span class="function">(<span class="params">value</span>) =&gt;</span> value + <span class="number">1</span></span><br></pre></td></tr></table></figure><p>E como só um argumento é esperado pela função, podemos omitir os parênteses:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> plusOne = <span class="function"><span class="params">value</span> =&gt;</span> value + <span class="number">1</span></span><br></pre></td></tr></table></figure><p><strong>Importante:</strong> Não é obrigatório omitir os parênteses. Eu, particularmente, prefiro deixar, pois acho que torna a leitura mais fácil. Mas é uma possibilidade. Com o tempo pode ser que você se acostume, então use da forma que achar melhor. Apenas siga um padrão do início ao fim do seu projeto =)</p><h2 id="Posso-substituir-todas-as-“function”-por-“arrow-function”"><a href="#Posso-substituir-todas-as-“function”-por-“arrow-function”" class="headerlink" title="Posso substituir todas as “function” por “arrow function”?"></a>Posso substituir todas as “function” por “arrow function”?</h2><p>Essa é uma ótima pergunta, e muitas pessoas <strong>não</strong> a fazem, apenas substituem e vida que segue.</p><p>Mas não é bem assim!</p><p>As <em>arrow functions</em> não foram criadas apenas para ser uma sintaxe mais exuta e substituir as <code>function</code> tradicionais. Elas têm alguns detalhes importantes que é preciso levar em consideração antes de saber se devemos ou não só sair substituindo tudo.</p><h2 id="Escopo-lexico"><a href="#Escopo-lexico" class="headerlink" title="Escopo léxico"></a>Escopo léxico</h2><p>Funções, ao serem criadas, geram um escopo próprio. E esse escopo só existe enquanto a função existe.</p><p>No JavaScript, temos a palavra chave <code>this</code>, que é bastante polêmica, pois na maioria das linguagens, essa palavra chave faz referência à um objeto criado à partir de um construtor, quando usada dentro de uma classe; ou quando usada dentro de um método de objeto, ela faz referência à esse objeto.</p><p>Mas isso nem sempre é verdade: é possível “injetar” o <code>this</code>, dependendo da forma que você executa uma função.</p><p>Se você não está por dentro desse assunto, recomendo <a href="https://blog.da2k.com.br/2015/01/30/javascript-como-invocar-funcoes/">esse post</a> que escrevi a um tempo atrás. Leia o artigo, e depois volte aqui que tudo vai fazer sentido. Pode ir. Eu espero =)</p><p>…</p><p>Já leu? Ótimo, vamos continuar! :D</p><p>O importante aqui é saber que, diferente das <code>function</code> tradicionais, você não consegue “injetar” o <code>this</code> em <em>arrow functions</em>. Isso mesmo!</p><p>Se o <code>this</code> for usado dentro de uma <em>arrow function</em>, esse <code>this</code> vai fazer referência ao objeto que ele <strong>já era referência</strong> no <strong>momento da criação</strong> da <em>arrow function</em>.</p><p>Ficou complicado de entender? Vamos ver alguns exemplos!</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getThis</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(getThis()) <span class="comment">// Objeto window</span></span><br></pre></td></tr></table></figure><p>Se executarmos a função <code>getThis</code>, criada no escopo global, em algum navegador, vamos ter como retorno o objeto <code>window</code>, pois quando uma função que têm o <code>this</code> dentro não for uma função construtora, nem um método de objeto, o <code>this</code> vai ser referência ao objeto global.</p><p>Mas se usarmos <code>&#39;use strict&#39;</code>, como você já deve saber, essa diretiva faz com que o <code>this</code> global seja <code>undefined</code>. Logo, esse é o resultado quando estamos executando nossa função em <em>strict mode</em>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getThis</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(getThis()) <span class="comment">// undefined</span></span><br></pre></td></tr></table></figure><p>E a questão interessante ao usar <em>arrow function</em> é exatamente essa: nos dois casos, a <em>arrow function</em> vai retornar o objeto <code>window</code>, por causa do escopo léxico. Lembre-se: o <code>this</code> dentro de uma <em>arrow function</em> sempre vai ser referência ao objeto que ele <strong>já era referência</strong> no <strong>momento da criação</strong> da <em>arrow function</em>. (nesse caso, o objeto <code>window</code>):</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> getThis = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(getThis()) <span class="comment">// Objeto window</span></span><br></pre></td></tr></table></figure><p>E usando <code>&#39;use strict&#39;</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> getThis = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">this</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(getThis()) <span class="comment">// Objeto window</span></span><br></pre></td></tr></table></figure><p>Uma outra situação bastante comum é ao usar um método de objeto:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> counter = &#123;</span><br><span class="line">  value: <span class="number">0</span>,</span><br><span class="line">  increment: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> ++<span class="keyword">this</span>.value</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(counter.increment()) <span class="comment">// 1</span></span><br><span class="line"><span class="built_in">console</span>.log(counter.increment()) <span class="comment">// 2</span></span><br></pre></td></tr></table></figure><p>Agora, ao tentar usar uma <em>arrow function</em> como método do objeto, olhe o que acontece:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> counter = &#123;</span><br><span class="line">  value: <span class="number">0</span>,</span><br><span class="line">  increment: <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> ++<span class="keyword">this</span>.value</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(counter.increment()) <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure><p>Veja que o valor retornado pelo método <code>increment</code> agora é <code>NaN</code>. E isso acontece porque o objeto está sendo criado no escopo global, logo, o método <code>increment</code> também está sendo criado nesse escopo, já que o objeto <code>counter</code> não está dentro de nenhuma função.</p><p>E outra coisa importante a notar é o valor de <code>value</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(counter.value) <span class="comment">// 0</span></span><br></pre></td></tr></table></figure><p>Veja que o valor de <code>value</code> não foi alterado! Logo, o <code>value</code> que está sendo exibido é um valor que foi criado no objeto global <code>window</code>, e para esse <code>value</code> é que foi atribuído o valor <code>NaN</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="built_in">window</span>.value) <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure><p>Com isso, fica claro que o <code>this</code> dentro de uma <em>arrow function</em> vai ser sempre referência ao objeto ao qual ele já era, no momento em que a função foi criada.</p><p>Essa regra vale para qualquer chamada de função que precise usar o <code>this</code> dentro, então preste atenção, ok? =)</p><p>Só mais um exemplo, apenas para complementar: eventos!</p><p>O método <code>addEventListener</code> sempre injeta o <code>this</code> dentro da função usada como listener desse evento.</p><p>Veja esse exemplo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> $input = <span class="built_in">document</span>.querySelector(<span class="string">'input[type="text"]'</span>)</span><br><span class="line">$input.addEventListener(<span class="string">'input'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'value:'</span>, <span class="keyword">this</span>.value)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br></pre></td></tr></table></figure><p>No exemplo acima, estou assumindo que o código vai ser executado em um ambiente onde existe um campo <code>input</code> do tipo <code>text</code>.</p><p>Ao começar a digitar algo dentro desse campo, podemos ver o valor do campo sendo exibido no <code>console</code>, pois o <code>this</code> dentro da função passada como listener do evento é injetado pelo <code>addEventListener</code>, fazendo referência ao objeto do DOM ao qual o evento foi atrelado.</p><p>Agora tente usar uma <em>arrow function</em> no lugar da <code>function</code> tradicional:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> $input = <span class="built_in">document</span>.querySelector(<span class="string">'input[type="text"]'</span>)</span><br><span class="line">$input.addEventListener(<span class="string">'input'</span>, () =&gt; &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'value:'</span>, <span class="keyword">this</span>.value)</span><br><span class="line">&#125;, <span class="literal">false</span>)</span><br></pre></td></tr></table></figure><p>Nesse caso, veja que o valor exibido no cosole é sempre <code>undefined</code> (a menos que exista um objeto no escopo em que a função foi criada, e esse objeto tenha uma propriedade <code>value</code>).</p><h2 id="Consideracoes"><a href="#Consideracoes" class="headerlink" title="Considerações"></a>Considerações</h2><p>Com tudo isso em mente, podemos considerar alguns pontos:</p><ul><li>se a função que você tem não depende do valor de algum <code>this</code>, você pode substituí-la por <em>arrow function</em> sem problemas;</li><li>evite usar o <code>this</code>. No caso do exemplo do evento, toda função listener de um evento recebe um objeto de evento, com uma propriedade <code>target</code>, que faz referência ao elemento que recebeu o evento. Use esse objeto se precisar manipular ou fazer qulquer coisa com o elemento que disparou o evento, ao invés de usar <code>this</code>. Dessa forma você evita os problemas vistos acima.</li></ul><p><strong>Parabéns!</strong> Agora você já sabe como usar corretamente as <em>arrow functions</em> sem problemas!</p><p>Já conhecia essa nova sintaxe de funções? Ficou com alguma dúvida? Faltou falar alguma coisa no post? Gostaria de sugerir um assunto para os próximos posts?</p><p>Deixe nos comentários! Ficarei muito feliz em ler e te responder :D</p><p>Até a próxima :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/uploads/2019/01/arrow-functions.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apesar de ser uma &lt;em&gt;feature&lt;/em&gt; bastante usada hoje em dia, algumas pessoas ainda não conhecem alguns segredos dessa nova sintaxe de funções em JavaScript.&lt;br&gt;Quer saber tudo o que as &lt;em&gt;arrow functions&lt;/em&gt; são capazes de fazer? Vem comigo que eu te mostro =)&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
  </entry>
  
  <entry>
    <title>Retrospectiva 2018</title>
    <link href="https://blog.da2k.com.br/2018/12/31/retrospectiva-2018/"/>
    <id>https://blog.da2k.com.br/2018/12/31/retrospectiva-2018/</id>
    <published>2018-12-31T20:30:29.000Z</published>
    <updated>2025-05-12T12:40:00.874Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2018/12/retrospectiva-2018.png" alt="Retrospectiva 2018"></p><p>Quer saber como foi meu ano? Vem comigo =)</p><a id="more"></a><h2 id="2017"><a href="#2017" class="headerlink" title="2017"></a>2017</h2><p>Acabei não escrevendo uma retrospectiva de 2017 para 2018, mas posso dizer que 2017 foi um ano sensacional pra mim. Muitas coisas boas aconteceram, e cada ano tem sido melhor. Mas o que posso dizer que marcou meu 2017 foi que comecei a cuidar melhor da minha saúde.</p><p>Desde sempre que eu tento começar a fazer exercícios físicos em casa ou na rua: caminhar, correr, etc., mas nunca conseguia seguir em frente. Depois de alguns dias caminhando / correndo, começava com um dia chuvoso ou muito frio e eu já parava. Não conseguia colocar foco.</p><p>Cheguei ao auge do meu peso com 95kg, de 2015 para 2016.</p><p>Em 2016 eu procurei alternativas para me alimentar melhor. Consegui perder 10kg, mas depois eu encontrei novamente 5kg desses 10, e travei nos 90kg.</p><p>Eu não entendia de fato como funcionava se alimentar de forma saudável, e principalmente não entendia como o corpo funcionava para que eu pudesse perder peso. Não estava feliz com meu corpo e com meu peso atual, e não somente por conta de estética, por causa da saúde mesmo: sentia muita preguiça, mal conseguia andar por algumas horas que já estava todo dolorido, postura toda errada - lombar virada num “U”, pescoço de dinossauro, sabe? haha :P</p><p>É engraçado lembrar hoje, mas é ruim viver assim. Eu tinha muitas dores na coluna - principalmente na região do pescoço e lombar.</p><p>Então em 12 de Julho de 2017 eu resolvi me matricular na academia e começar a malhar. Algumas pessoas me falaram que fazer musculação era chato, que eu não iria gostar, que iria desistir, mas mesmo assim resolvi tentar.</p><p>E não é que tomei gosto pela coisa! Gostei tanto que comecei a estudar sobre como executar corretamente os exercícios - obrigado YouTube 💙 -, sobre alimentação saudável, e acabei aprendendo o segredo para emagrecer: MATEMÁTICA! - Se estiver interessada(o) no assunto, deixe nos comentários que eu faço um post especificamente falando sobre isso, com detalhes! Mas você pode pesquisar no YouTube por “déficit calórico”, “dieta flexível”, que são assuntos que vão ajudar bastante a entender a ideia!</p><p>Resultado: nesses 6 meses finais de 2017 consegui perder de 4kg a 5kg, e cheguei nos 80kg, fechando o ano com 17% de BF*! Foi uma grande vitória =)</p><blockquote><ul><li>BF = Body Fat, ou Porcentagem de Gordura Corporal.</li></ul></blockquote><h2 id="2018"><a href="#2018" class="headerlink" title="2018"></a>2018</h2><p>Agora começando com 2018: ainda falando em saúde, só pra finalizar, comecei o ano com 17% de BF e estou finalizando com 12% ~ 13%!</p><p>A meta é chegar a 5% ~ 7% até final de 2019 :D</p><p>Comecei também a fazer Muay Thai no final de Novembro, pois quase não estava fazendo exercícios cardiovasculares. De vez em quando eu jogo futebol, mas ultimamente tem sido bem de vez em quando mesmo haha!</p><p>A única arte marcial que eu tinha praticado na vida foi Capoeira, quando eu era moleque (devia ter entre 9 a 11 anos), e nunca mais fiz nada.</p><p>Por enquanto o Muay Thai tem me surpreendido, estou gostando bastante!</p><p>Falando do lado profissional: participei de muitos eventos esse ano, palestrei em alguns, mas o mais sensacional de tudo é sempre conhecer pessoas novas!</p><p>Conhecer pessoas que eu admiro, conhecer meus alunos pessoalmente, ouvir relatos de que o conteúdo que eu tenho compartilhado tem sido útil para eles conseguirem emprego - alguns até fora do país - é o que me deixa mais feliz e animado para os novos projetos que virão em 2019!</p><p>E o objetivo para 2019 é: <strong>palestrar menos</strong> e <strong>participar mais</strong>!</p><p>Dar palestras tem sim o seu valor, mas o networking e o engajamento das pessoas é o que fortalece nossa comunidade =)</p><p>Tentei uma nova experiência em 2018, que foram os cursos presenciais!</p><p>Fizemos duas edições em Joinville / SC do curso React Ninja. Curti bastante esse formato de curso. Em 2019 teremos novidades com relação a isso :D</p><p>Enfim, rolou muita coisa legal em 2018:<br>Viajei, conheci novas cidades, visitei parques nas cidades, andei de kart, cuidei da minha saúde, mudei de casa, assei carne (muito importante haha), participei de meetups e eventos, postei memes no Facebook e conteúdo sério e relevante no Twitter, aprendi receitas fitness, revi amigas e amigos, conheci novas(os), tive tempo para a família, para a minha esposa, fizemos trilha, fomos à praia - conheci a praia de Daniela em Floripa, que lugar sensacional! Recomendo se você ainda não conhece :D - ufa!</p><p>Foi muita coisa! Mas ficou muita coisa ainda por fazer.</p><p>Alguns planos / projetos eu não consegui terminar (alguns nem começar).</p><p>Mas isso vai ficar de lição para 2019: planejar muito bem os próximos passos, medir, testar, me organizar, estudar muito, pois ainda tenho muito a aprender, e dar meu melhor ajudar a comunidade, principalmente àqueles(as) mais necessitados e com menos condições financeiras!</p><p>Tenho certeza que 2019 vai ser um ano excelente!</p><p>Obrigado por ler até aqui, e espero que o seu 2019 seja lindo! Se 2018 não foi tudo aquilo, 2019 com certeza será! :D</p><p>Cuide de você. Cuide da sua saúde, cuide da sua mente. Estude, mas também descanse. Se organize, e seja feliz =)</p><p>PS.: E vou começar a tirar as teias desse blog também, pois tem muito conteúdo legal que precisa ser compartilhado!</p><p>Que venha 2019! :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2018/12/retrospectiva-2018.png&quot; alt=&quot;Retrospectiva 2018&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quer saber como foi meu ano? Vem comigo =)&lt;/p&gt;
    
    </summary>
    
      <category term="retrospectiva" scheme="https://blog.da2k.com.br/categories/retrospectiva/"/>
    
    
  </entry>
  
  <entry>
    <title>Objetos - Referências de valores em JavaScript</title>
    <link href="https://blog.da2k.com.br/2017/01/25/objetos-referencias-de-valores-em-javascript/"/>
    <id>https://blog.da2k.com.br/2017/01/25/objetos-referencias-de-valores-em-javascript/</id>
    <published>2017-01-25T20:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.874Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2017/01/object-reference-javascript.png" alt=""></p><p>Vamos conversar um pouco sobre objetos em JavaScript? Vem comigo então =)</p><a id="more"></a><p>Em todas as linguagens (ao menos todas que eu conheço :P), existem duas formas de você passar valores:</p><ul><li>Por referência;</li><li>Por valor.</li></ul><p>Quando eu digo “passar valores”, eu estou me referindo à:</p><ul><li>Atribuir um valor à uma variável;</li><li>Atribuir um valor à uma propriedade ou método de um objeto;</li><li>Passar argumentos para uma função (ou método de um objeto).</li></ul><p>Por exemplo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> string = <span class="string">'uma string qualquer'</span></span><br><span class="line"><span class="keyword">var</span> objeto = &#123;&#125;</span><br></pre></td></tr></table></figure><p>No exemplo acima, eu atribuí o valor <code>&#39;uma string qualquer&#39;</code> à variável <code>string</code>,<br>e também atribuí um novo objeto à variável <code>objeto</code>.</p><p>Até aqui, nada de anormal. Mas existem alguns conceitos por detrás dessas atribuições:</p><p>O valor <code>&#39;uma string qualquer&#39;</code> foi passado para a variável <code>string</code> por <strong>valor</strong>.</p><p>Já o objeto passado para a variável <code>objeto</code>, foi passado por <strong>referência</strong>.</p><p>E para explicar a diferença entre essas duas formas de passagem <strong>passagem de valor</strong>, precisamos entender algumas coisas da linguagem <strong>JavaScript</strong>.</p><h2 id="Tipos-de-dados-em-JavaScript"><a href="#Tipos-de-dados-em-JavaScript" class="headerlink" title="Tipos de dados em JavaScript"></a>Tipos de dados em JavaScript</h2><p>JavaScript tem alguns tipos de dados que podemos separar em:</p><ul><li>Tipos primitivos;</li><li>Objetos.</li></ul><p>Os tipos primitivos da linguagem são: <code>number</code>, <code>string</code>, <code>boolean</code>, <code>null</code> e <code>undefined</code>.<br>(<code>Symbol</code> também é um tipo primitivo, que veio no novo pacotinho do ES6/2015).</p><p>Todos os outros tipos de dados em JavaScript são do tipo <code>object</code>:</p><ul><li>Objetos;</li><li>Funções;</li><li>Arrays;</li><li>Regex;</li><li>etc.</li></ul><p><em>Tá, e daí? O que isso tem a ver com o post?</em></p><p>Aí que está: tem tudo a ver! E agora que você conhece quem são os tipos primitivos e quem são os objetos,<br>eu já posso te dizer que:</p><ul><li>Tipos primitivos são passados por <strong>valor</strong>, e são <strong>imutáveis</strong>;</li><li>Objetos são passados por <strong>referência</strong>, e são <strong>mutáveis</strong>.</li></ul><p>Guarde bem essa informação, ela vai ser útil logo, logo =)</p><h2 id="Passagem-de-dados-“por-valor”"><a href="#Passagem-de-dados-“por-valor”" class="headerlink" title="Passagem de dados “por valor”"></a>Passagem de dados “por valor”</h2><p>Quando é feita uma passagem de tipos <strong>por valor</strong>, significa que o valor foi <strong>copiado</strong>.</p><p>Vamos aos exemplos:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span></span><br><span class="line"><span class="keyword">var</span> b = <span class="number">10</span></span><br><span class="line"><span class="built_in">console</span>.log(a === b) <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>No exemplo, eu atribuí o valor <code>10</code> para as variáveis <code>a</code> e <code>b</code>. O <code>10</code> - tipo primitivo <code>number</code> - foi passado <strong>por valor</strong>, ou seja, ele foi <strong>copiado</strong><br>para as variáveis <code>a</code> e <code>b</code>. Ao tentar comparar seus valores, vemos que o resultado é <code>true</code>, ou seja, é o mesmo valor.</p><p>Agora vamos ver o que acontece se tentarmos fazer o mesmo com um objeto:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> b = &#123;&#125;</span><br><span class="line"><span class="built_in">console</span>.log(a === b) <span class="comment">// false</span></span><br></pre></td></tr></table></figure><p><em>O resultado da comparação deu <code>false</code>? Por quê?</em></p><h2 id="Passagem-de-tipos-“por-referencia”"><a href="#Passagem-de-tipos-“por-referencia”" class="headerlink" title="Passagem de tipos “por referência”"></a>Passagem de tipos “por referência”</h2><p>Lembra que eu falei ali em cima que <strong>objetos são passados por referência</strong>? Então, vou explicar o que está acontecendo.</p><p>A cada vez que você cria um novo objeto, o JavaScript reserva um espaço para esse objeto <strong>na memória</strong>.<br>Sim, alguns bytes da memória do seu computador são reservados para guardar as informações desse novo objeto criado.</p><p>Usar as chaves <code>{}</code> é o mesmo que <code>new Object()</code>, só que mais rápido (performance não vem ao caso agora).</p><p>O que eu quero dizer é que, sempre que você faz isso no seu código: <code>{}</code>; você está criando um novo objeto.</p><p>E a cada novo objeto criado, um novo espaço na memória é ocupado.</p><p><em>Huummmm, acho que estou sacando xD</em></p><p>É isso mesmo! O resultado do exemplo acima deu <code>false</code>, porque são dois objetos diferentes! Cada um foi criado em um espaço<br>diferente da memória!</p><p>O que acontece quando você cria um novo objeto e o atribui à uma variável, é que, a partir desse momento, essa variável<br>passa a <strong>apontar</strong> para o objeto criado. É o que chamamos de <strong>ponteiro</strong>.</p><p>Logo, se fizermos:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> b = a</span><br><span class="line"><span class="built_in">console</span>.log(a === b) <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>Ou seja: a operação acima <strong>não copiou</strong> o valor do objeto que foi atribuido à <code>a</code> para a variável <code>b</code>;<br>o que aconteceu foi que, agora as duas variáveis apontam para o <strong>mesmo objeto</strong>.</p><ul><li>O objeto foi criado e atribuído à variável <code>a</code>;</li><li>Criamos uma nova variável <code>b</code>, e atribuímos o valor de <code>a</code> para <code>b</code>;</li><li>Como o valor de <code>a</code> é um objeto, o valor não foi copiado, mas sim <strong>passado por referência</strong>;</li><li>E agora as duas variáveis são <strong>ponteiros</strong>, que <strong>apontam</strong> para o mesmo local na memória onde está esse objeto.</li></ul><p>Deu pra entender?</p><p><em>Tá, entendi, mas por que isso é tão importante assim?</em></p><p>Pelo seguinte motivo: lembra que eu falei ali em cima que <strong>objetos são mutáveis</strong> e tipos primitivos não?<br>Eis a treta:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> b = a</span><br><span class="line">a.prop = <span class="string">'any value'</span></span><br><span class="line"><span class="built_in">console</span>.log(b.prop) <span class="comment">// 'any value'</span></span><br></pre></td></tr></table></figure><p>Olha só o que aconteceu: como objetos são <strong>mutáveis</strong>, significa que, mesmo após ter criado o objeto,<br>você pode <strong>modificá-lo</strong>, adicionando ou removendo propriedades e métodos.</p><p>No exemplo acima, eu fiz o seguinte:</p><ul><li>Criei um novo objeto e atribuí à variável <code>a</code>;</li><li>Criei uma variável <code>b</code>, e atribuí o objeto passado para <code>a</code>, por referência;</li><li>Usando a variável <code>a</code>, eu criei uma nova propriedade chamada <code>prop</code>, com a string <code>&#39;any value&#39;</code>;</li><li>Ao verificar o que tem na propriedade <code>prop</code> da variável <code>b</code>, vemos que lá está o valor que foi atribuído à variável <code>a</code>.</li></ul><p>E isso acontece simplesmente porque o objeto atribuido para <code>a</code> e <code>b</code> é o mesmo!</p><p>Esse comportamento acontece com qualquer tipo de dado que seja um objeto. Olhe, por exemplo, com uma função:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="string">'a'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> b = a</span><br><span class="line"></span><br><span class="line">a.prop = <span class="string">'any value'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(b()) <span class="comment">// 'a'</span></span><br><span class="line"><span class="built_in">console</span>.log(b.prop) <span class="comment">// 'any value'</span></span><br></pre></td></tr></table></figure><p>Veja que, como funções também são objetos, você também pode adicionar novas propriedades e métodos.</p><p>No exemplo acima, eu criei uma função, e adicionei uma propriedade <code>prop</code>. Perceba que a função é mutável,<br>ou seja, eu consigo criar novas propriedades mesmo depois que a função já foi criada, e veja como ela é<br>passada <strong>por referência</strong> para <code>b</code>, pois eu fiz as modificações na variável <code>a</code>, e elas foram refletidas<br>também na variável <code>b</code>.</p><p>Acho que ficou claro até aqui, certo? Se não ficou, só comenta aí no post que a gente discute sobre o assunto =)</p><p>Por agora, vamos prosseguir =)</p><h2 id="Passando-tipos-por-referencia-via-argumento-de-funcao"><a href="#Passando-tipos-por-referencia-via-argumento-de-funcao" class="headerlink" title="Passando tipos por referência, via argumento de função"></a>Passando tipos por referência, via argumento de função</h2><p>Você pode passar referências de objetos não somente usando atribuição, mas também como <strong>argumentos</strong> para uma função.<br>Veja o exemplo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">updateObject</span> (<span class="params">object</span>) </span>&#123;</span><br><span class="line">  object.newProp = <span class="string">'vixx, mudou mesmo!'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> object = &#123;&#125;</span><br><span class="line">updateObject(object)</span><br><span class="line"><span class="built_in">console</span>.log(object) <span class="comment">// &#123; newProp: 'vixx, mudou mesmo!' &#125;</span></span><br></pre></td></tr></table></figure><p>Olha que loucura o que aconteceu aqui em cima:</p><ul><li>Criei uma nova função chamada <code>updateObject</code>, que recebe via argumento um objeto qualquer, e adiciona uma nova popriedade <code>newProp</code> nesse objeto, com o valor <code>&#39;vixx, mudou mesmo!&#39;</code>;</li><li>Logo abaixo, crio um novo objeto e atribuo à variável <code>object</code>;</li><li>Invoco a função <code>updateObject</code>, passando por parâmetro o valor da variável <code>object</code>. Lembre-se que objetos são passados <strong>por referência</strong>;</li><li>Logo após invocar a função - que não retorna valor algum - eu testo o valor da variável <code>object</code>, e olhe o que aconteceu: uma nova propriedade <code>newProp</code> foi criada e o valor <code>&#39;vixx, mudou mesmo!&#39;</code> atribuído!</li></ul><p><em>Nossa que legal! Então quer dizer que eu posso passar qualquer objeto para uma função, e modificá-lo lá dentro que, quando eu pegar meu objeto novamente, ele vai estar atualizado?</em></p><p>Sim, você pode. Mas <strong>NÃO DEVE!</strong>. Isso se chama <strong>efeito colateral</strong> (ou <em>side effect</em>), e isso é assunto para um outro post (que vai sair em breve xD).</p><p>Por enquanto, você só precisa saber que <strong>NÃO DEVE</strong> fazer isso, de forma alguma.</p><p>Entender essa forma de <strong>passagem de valores</strong> em <strong>JavaScript</strong> é muito importante se você quer aprender a linguagem de verdade.</p><p>Entendendo isso, você consegue, no mínimo, duas coisas:</p><ul><li>melhorar a performance da sua aplicação (pois não fica criando objetos sem necessidade);</li><li>evita bugs causados por efeitos colaterais (pois não vai modificar um objeto diretamente, mas vai trabalhar com imutabilidade).</li></ul><p>Imutabilidade é o assunto do nosso próximo post, aguarde!</p><p>Enquanto isso: deu pra entender o assunto do post? Ficou alguma dúvida? Gostaria de acrescentar algo? Comenta aí embaixo e até o próximo! :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2017/01/object-reference-javascript.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vamos conversar um pouco sobre objetos em JavaScript? Vem comigo então =)&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="objetos" scheme="https://blog.da2k.com.br/tags/objetos/"/>
    
      <category term="valores por referência" scheme="https://blog.da2k.com.br/tags/valores-por-referencia/"/>
    
  </entry>
  
  <entry>
    <title>Retrospectiva 2016</title>
    <link href="https://blog.da2k.com.br/2017/01/01/retrospectiva-2016/"/>
    <id>https://blog.da2k.com.br/2017/01/01/retrospectiva-2016/</id>
    <published>2017-01-01T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.874Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2017/01/retrospectiva-2016.png" alt="Retrospectiva 2016"></p><p>2016 foi um ano conturbado para o nosso país (e para boa parte do mundo), mas gostaria de compartilhar nesse post as coisas boas que aconteceram comigo nesse ano =)</p><a id="more"></a><p>Bom, não lembro exatamente a ordem que muitas coisas aconteceram, mas posso dizer que foi um ano sensacional! Aprendi, criei, participei. Só tenho a agradecer por tudo o que aconteceu &lt;3</p><h2 id="E-2016-comecou"><a href="#E-2016-comecou" class="headerlink" title="E 2016 começou"></a>E 2016 começou</h2><p>Logo no início do ano, comecei a estudar sobre <a href="http://redux.js.org/" target="_blank" rel="noopener">Redux</a>. Já estava na pegada do <a href="https://facebook.github.io/react/" target="_blank" rel="noopener">React</a> a algum tempo, e estava ouvindo algumas pessoas falarem sobre Redux, até que eu fui ver qual era a dele, até me apaixonar pela simplicidade de como ele faz as coisas acontecerem =)</p><p>No <a href="https://zimp.me" target="_blank" rel="noopener">Zimp</a>, comecei a escrever uma <a href="https://github.com/ZimpFidelidade/node-magazine-luiza" target="_blank" rel="noopener">lib em Node</a> que consumiria o webservice da Magazine Luiza - que responde em XML - para utilizar com Node, com a resposta em JSON. Finalizei a primeira versão no dia 27/01.</p><p>Para treinar minha escrita em inglês, criei o <a href="https://medium.com/daily-js-tips" target="_blank" rel="noopener">Daily JS Tips</a> no Medium. Escrevi apenas alguns poucos posts, mas já foi válido pra começar a fazer algo em inglês.</p><p>Resolvi também sair da vida sedentária, e começar a caminhar diariamente, ao menos 1h por dia. Obviamente não consegui fazer todos os dias, até porque Joinville é conhecida carinhosamente como “Chuville”, e deixando de caminhar alguns dias por conta da chuva, já começa a bater um desânimo. Mas em vista dos anos anteriores em que eu não fazia praticamente nada de exercícios, esse foi um ano, digamos, interessante. Comecei o ano com 89kg e terminei com 84kg. Já foi um bom começo xD</p><p>Diminuí drasticamente também o consumo de carboidratos e açúcar, sem contar no corte total de café (que eu quase não tomava mesmo) e leite.</p><p>Em fevereiro, dei minha primeira (e única) palestra do ano no <a href="https://github.com/fdaciuk/talks#femug-joinville" target="_blank" rel="noopener">Femug Joinville</a>, sobre Redux.</p><p>Em março, lancei o <a href="https://github.com/fdaciuk/hmh" target="_blank" rel="noopener">HMH</a>. Até escrevi um <a href="/2016/03/11/hmh-calculando-horas-com-javascript/">post sobre ele</a> - o único post de 2016 aqui no blog :| - prometo melhorar isso em 2017 =)</p><p>Antes desse projeto, eu tinha alguns padrões próprios para lint de código, e você deve saber o quanto isso é um processo chato de se manter e configurar. Por isso eu passei a utilizar o <a href="https://github.com/feross/standard" target="_blank" rel="noopener">standard</a>, que é um padrão pré-definido para escrita de código em JS usado em várias libs open source. Gostei e adotei para todos os meus projetos a partir de então.</p><p>Em algum momento do ano, o <a href="https://github.com/LFeh" target="_blank" rel="noopener">Fe</a> teve uma ideia de criar um fórum de discussão no GitHub, para que as discussões sobre desenvolvimento saíssem do ambiente fechado do Facebook, e fossem para um ambiente que fizesse mais sentido. Foi - e está sendo - um sucesso. Muitos devs engajaram na ideia, e muitas discussões de alto nível têm surgido por lá! Se você ainda não conhece o fórum, não perde tempo e vai <a href="https://github.com/frontendbr/forum" target="_blank" rel="noopener">lá dar uma olhada</a> (tá, termina de ler o post antes :P)</p><p>Em maio, tive a oportunidade de ajudar a organizar o <a href="https://github.com/scdevsummit/sc-dev-summit-website" target="_blank" rel="noopener">SC Dev Summit</a>. Foi um evento sensacional, de dois dias, sobre PHP (no primeiro dia) e Frontend (no segundo dia).</p><p>Criei uma lib bastante simples, chamada <a href="https://github.com/fdaciuk/iscpf" target="_blank" rel="noopener">iscpf</a>, que apenas testa se um número (ou string) entrado é um CPF válido.</p><p>Também tive a oportunidade de começar a desenvolver o curso <a href="/curso-reactjs-ninja/">React Ninja</a>, que ainda está em andamento, mas já tenho recebido feedbacks sensacionais sobre o curso!</p><p>Comecei um <a href="https://www.youtube.com/queroserninja" target="_blank" rel="noopener">canal no Youtube</a> para compartilhar conhecimento. Inicialmente, liberei uma parte do primeiro módulo do curso React Ninja, mas a ideia é que várias dicas sejam compartilhadas nesse canal. Aproveita e já se inscreve lá =)</p><p>E com o trabalho pesado de quase um ano inteiro, lançamos o <a href="https://zimp.me/" target="_blank" rel="noopener">Zimp</a>, empresa da qual sou sócio e tenho muito orgulho de todos que trabalharam nesse projeto e fizeram - e ainda estão fazendo - acontecer!</p><p>Tivemos até uma festa de lançamento do projeto na <a href="https://www.iflyworld.com/sao-paulo/" target="_blank" rel="noopener">iFly</a> em São Paulo! Foi animal! :D</p><p>Para sair um pouco mais da zona de conforto, comecei a estudar <a href="https://www.haskell.org/" target="_blank" rel="noopener">Haskell</a>. Tenho curtido muito estudar uma linguagem puramente funcional! Criei uma organização no GitHub onde eu fico fazendo testes de várias coisas, e não poderia faltar o <a href="https://github.com/playgd/haskell-playground" target="_blank" rel="noopener"><em>playground</em> para o Haskell</a> =)</p><p>Por conta do curso React Ninja, eu comecei a escrever alguns componentes para usar como exemplo no curso, mostrando desde a parte de testes unitários, testes visuais, que garantem que cada estado do componente funciona corretamente, até o componente em si. E um que eu acabei lançando open source foi o <a href="https://github.com/fdaciuk/react-trianglify" target="_blank" rel="noopener">react-trianglify</a>, um <em>wrapper component</em> React para usar com o <a href="https://github.com/qrohlf/trianglify" target="_blank" rel="noopener">trianglify</a>.</p><p>Já tenho usado o Vim como meu editor de código padrão desde o ano passado, e esse ano eu conheci o <a href="https://tmux.github.io/" target="_blank" rel="noopener">tmux</a> - apresentado pelo <a href="https://github.com/danjesus" target="_blank" rel="noopener">Dan Jesus</a> -, e comecei a utilizá-lo a partir do projeto <a href="http://byobu.co/" target="_blank" rel="noopener">Byobu</a>, que tem alguns atalhos mais “fáceis” de usar, para que você possa começar a se acostumar com o Tmux. Achei o projeto bem interessante, e só tenho elogios até agora. Em breve pretendo gravar um vídeo mostrando como ele funciona =)</p><p>Um outro projetinho simples que eu fiz esse ano também foi o <a href="https://github.com/fdaciuk/is" target="_blank" rel="noopener">@fdaciuk/is</a>, que é basicamente uma lib que facilita checar tipos em JavaScript.</p><p>E finalmente, no final de 2016, eu saí de Joinville e me mudei para Curitiba. Agora estou morando na Rússia brasileira! Pretendo colaborar e aprender muito com as comunidades de desenvolvimento por aqui. 2017 promete! :D</p><p>Claro que muito mais coisas aconteceram, mas esses são os acontecimentos que eu lembro. Deixei um lembrete diário no meu <a href="https://keep.google.com/" target="_blank" rel="noopener"><em>Google Keep</em></a> para que eu anote tudo o que acontecerá comigo. Assim, quando for fazer a retrospectiva de 2017, terei informações mais palpáveis.</p><p>Um ponto negativo desse ano foi que eu não pude participar de muitos eventos. Apenas marquei presença na BrazilJS, pois o ingresso já estava comprado desde o ano passado (e inclusive já garanti o ingresso da próxima edição, recomendo que você faça o mesmo xD), e no <a href="http://frontinfloripa.com.br/" target="_blank" rel="noopener">Front in Floripa</a>, que foi sensacional!</p><p>Enfim, a cada dia das nossas vidas nós precisamos fazer escolhas, escolher o que fazer, o que priorizar. Já vi muitos amigos falando - e eu também já falei isso por muitas vezes - que gostaria que o dia tivesse mais de 24h para poder colaborar mais com projetos open source, escrever mais artigos, fazer mais…</p><p>Mas a realidade é que todos temos 24h por dia, não tem como ter mais do que isso. O que faz a diferença não é o que você precisar de mais tempo para fazer mais coisas, mas sim o que você <strong>prioriza</strong> em 24h do seu dia.</p><p>Em 2016 precisei dar mais prioridade para projetos internos (<a href="https://zimp.me" target="_blank" rel="noopener">o Zimp</a>, <a href="/cursos">meus cursos</a>, etc), por isso não escrevi tanto aqui no blog, mas eu sabia que isso poderia acontecer.</p><p>Já em 2017, vou separar um tempo da minha semana para escrever ao menos 1 post por semana. E tentar escrever ao menos 1 em português e 1 em inglês. E eu sei que para isso acontecer, só vai depender de mim mesmo, organizando meu tempo, e priorizando as tarefas corretas para que a procrastinação não tome conta do meu tempo, e eu chegue ao final de 2017 sem ter feito nada do que eu queria ter feito.</p><p>Sim, é difícil. É preciso foco, determinação e organização. Mas a cada ano nós podemos aprender mais, e sermos melhores que o ano que passou.</p><p>Se eu pudesse deixar uma dica para esse ano, seria: repense suas prioridades. Estude JS puro. Estude inglês.</p><p>E que você tenha um ótimo 2017! Que nós possamos focar nas nossas prioridades, e realizar o que precisamos realizar esse ano, para chegar em dezembro e sermos surpreendidos positivamente com o que foi feito! :D</p><p>Ah, se você também escreveu sua retrospectiva, comenta ae que eu vou ficar muito feliz em ler :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2017/01/retrospectiva-2016.png&quot; alt=&quot;Retrospectiva 2016&quot;&gt;&lt;/p&gt;
&lt;p&gt;2016 foi um ano conturbado para o nosso país (e para boa parte do mundo), mas gostaria de compartilhar nesse post as coisas boas que aconteceram comigo nesse ano =)&lt;/p&gt;
    
    </summary>
    
      <category term="retrospectiva" scheme="https://blog.da2k.com.br/categories/retrospectiva/"/>
    
    
  </entry>
  
  <entry>
    <title>hmh - Calculando horas com JavaScript</title>
    <link href="https://blog.da2k.com.br/2016/03/11/hmh-calculando-horas-com-javascript/"/>
    <id>https://blog.da2k.com.br/2016/03/11/hmh-calculando-horas-com-javascript/</id>
    <published>2016-03-11T13:25:42.000Z</published>
    <updated>2025-05-12T12:40:00.858Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2016/03/how-many-hours.png" alt=""></p><p><code>hmh - How many hours?</code> foi uma ferramenta que eu resolvi criar, pois precisava fazer alguns cálculos com horas, mas não achei nada que eu pudesse usar, assim, “a toque de caixa”.<br>O projeto está no GitHub, <a href="https://github.com/fdaciuk/hmh" target="_blank" rel="noopener">nesse link</a>. Quer saber como foi desenvolvido, desde a ideia, os testes até a publicação? Então vem comigo que eu te mostro :D</p><a id="more"></a><h2 id="O-problema"><a href="#O-problema" class="headerlink" title="O problema"></a>O problema</h2><p>O que me motivou a criar a ferramenta foi: eu precisava calcular, de forma fácil, as horas que eu estava trabalhando em algum projeto. Eu deixava o tempo anotado em algum lugar - pois nem sempre a tarefa era finalizada de uma vez, às vezes era necessário começar outra sem terminar a primeira - e depois eu precisava calcular o tempo total que eu gastei nessa tarefa.</p><p>Isso ajuda pra que você saiba exatamente quanto tempo gasta para fazer cada coisa, ficando mais fácil “orçar” quando tempo você irá precisar para fazer algo parecido futuramente.</p><h2 id="Necessidade"><a href="#Necessidade" class="headerlink" title="Necessidade"></a>Necessidade</h2><p>O que eu precisava, naquele momento, era de:</p><ul><li>uma forma onde eu pudesse entrar com um horário inicial e um horário final, e saber quanto tempo foi gasto nesse meio tempo;</li><li>uma forma de somar esses intervalos, para saber o tempo total gasto na tarefa;</li><li>uma forma de saber quanto tempo por dia eu ainda precisaria trabalhar dentro da <em>sprint</em> (sim, usando <strong>SCRUM</strong>) para saber se eu teria horas sobrando para encaixar alguma outra tarefa, ou se eu já tinha esgotado meu tempo.</li></ul><p>Com essas informações, ficaria mais simples para que eu pudesse planejar as próximas <em>sprints</em> com uma precisão maior.</p><h2 id="A-solucao"><a href="#A-solucao" class="headerlink" title="A solução"></a>A solução</h2><p>Antes de fazer a lib, pesquisei para ver se encontraria algo já pronto que eu pudesse utilizar, e talvez até colaborar no desenvolvimento. Enfim, não achei nada que resolvesse o que eu precisava de forma fácil (inclusive, se você souber de alguma ferramenta que faça isso, deixe nos comentários que eu preciso saber :D).</p><p>Assim surgiu o <code>hmh</code>! :grin:</p><h2 id="O-nome"><a href="#O-nome" class="headerlink" title="O nome"></a>O nome</h2><p>O nome é uma abreviação para <code>How many hours?</code>, pois eu precisava saber <strong>quantas horas</strong> eu gastei, e quantas horas eu tinha disponível. Inicialmente eu pensei em fazer uma [<strong>CLI</strong>], pois como eu fico o dia todo com o terminal aberto, seria bem simples simplesmente digitar as horas ali e ver o resultado, passando alguns parâmetros para a CLI.</p><p>Mas depois eu percebi que isso também poderia ser usado para outras coisas, então faria mais sentido criar uma lib com toda a lógica que eu precisava, e então criar a CLI, consumindo essa lib.</p><p>Você pode ver o código da lib <a href="https://github.com/fdaciuk/hmh" target="_blank" rel="noopener">aqui</a> e da CLI <a href="https://github.com/fdaciuk/hmh-cli" target="_blank" rel="noopener">aqui</a>.</p><h2 id="Como-a-lib-funciona"><a href="#Como-a-lib-funciona" class="headerlink" title="Como a lib funciona?"></a>Como a lib funciona?</h2><p>O uso da lib é bastante simples: para instalar, execute:</p><figure class="highlight console"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save hmh</span><br></pre></td></tr></table></figure><p>Então é só usar! A lib tem 4 métodos: <code>sum</code>, <code>sub</code>, <code>diff</code> e <code>div</code>, que servem para os propósitos que citei acima.</p><p>O retorno desses métodos vai ser sempre um horário, um valor em <code>horas</code> e <code>minutos</code>.</p><p>Exemplo:</p><p>Imagine que você trabalhou um tempo em um projeto, e quer somar todo esse tempo. Só precisa passar o tempo por parâmetro para o método <code>sum</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(hmh.sum(<span class="string">'1h 20m 15m 2h 40m'</span>)) <span class="comment">// '4h 15m'</span></span><br></pre></td></tr></table></figure><p>E o resultado é a string <code>&#39;4h 15m&#39;</code>. Se você quiser ver o resultado somente em minutos, passe <code>minutes</code> como segundo parâmetro:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(hmh.sum(<span class="string">'1h 20m 15m 2h 40m'</span>, <span class="string">'minutes'</span>)) <span class="comment">// '255m'</span></span><br></pre></td></tr></table></figure><p>O método <code>sub</code> funciona da mesma forma, mas ele <code>subtrai</code> valores.</p><p>O método <code>diff</code> mostra a diferença entre duas horas. Imagine que você começou a trabalhar em uma tarefa às 8h15m da manhã e parou às 11h30m. Quanto tempo se passou?</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(hmh.diff(<span class="string">'8h 15m'</span>, <span class="string">'11h 30m'</span>)) <span class="comment">// '3h 15m'</span></span><br></pre></td></tr></table></figure><p>E ele mostra o resultado! Para ver em minutos, mesmo esquema dos outros métodos: como último parâmetro, passe <code>minutes</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(hmh.diff(<span class="string">'8h 15m'</span>, <span class="string">'11h 30m'</span>, <span class="string">'minutes'</span>)) <span class="comment">// '195m'</span></span><br></pre></td></tr></table></figure><p>E por último, o método <code>div</code>. Digamos que você trabalha em um projeto, e vende horas de manutenção. Você ainda tem <code>7h</code> para mexer nesse projeto nos próximos 4 dias. Quantas horas por dia você pode trabalhar para completar as <code>7h</code>? Simples: é só dividir <code>7h</code> em 4 dias:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(hmh.div(<span class="string">'7h'</span>, <span class="number">4</span>)) <span class="comment">// '1h 45m'</span></span><br></pre></td></tr></table></figure><p>Você pode trabalhar <code>1h 45m</code> por dia =)</p><h2 id="Command-Line-Interface"><a href="#Command-Line-Interface" class="headerlink" title="Command Line Interface"></a>Command Line Interface</h2><p>Mas isso seria mais útil se eu pudesse usar isso direto no terminal. Por isso eu fiz o <code>hmh-cli</code>, que também é bastante simples de usar!</p><p>Primeiro de tudo, instale globalmente:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[sudo] npm i -g hmh-cli</span><br></pre></td></tr></table></figure><p>Os métodos são os mesmos da lib, que você pode passar por parâmetro, como <code>--sum</code>, <code>--sub</code>, <code>--diff</code> e <code>--div</code>.</p><p>Espaços em branco a mais ou a menos são ignorados, tanto na lib quanto na CLI. Mas, no caso dos métodos <code>--diff</code> e <code>--div</code> da CLI, que precisam ter 2 parâmetros, você pode fazer de duas formas:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hmh --diff <span class="number">8</span>h15m <span class="number">11</span>h30m</span><br></pre></td></tr></table></figure><p>Juntando as horas e minutos, e separando os parâmetros por espaço. Ou ainda, usando aspas:<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hmh --diff <span class="string">"8h 15m"</span> <span class="string">"11h 30m"</span></span><br></pre></td></tr></table></figure></p><p>O resultado é o mesmo =)</p><p>Para o método de divisão, mesmo esquema:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hmh --div <span class="number">7</span>h20m <span class="number">4</span></span><br></pre></td></tr></table></figure><p>ou</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hmh --div <span class="string">"7h 20m"</span> <span class="number">4</span></span><br></pre></td></tr></table></figure><p>E para ter a saída em minutos, use o parâmetro <code>-o minutes</code> ou <code>--output minutes</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hmh --div <span class="string">"7h 20m"</span> <span class="number">4</span> -o minutes</span><br></pre></td></tr></table></figure><h2 id="O-desenvolvimento"><a href="#O-desenvolvimento" class="headerlink" title="O desenvolvimento"></a>O desenvolvimento</h2><p>Nos próximos posts, vou abordar toda a etapa de desenvolvimento da lib, testes, integração com CI e a criação da CLI.</p><p>Fique ligado! :D</p><hr><p>Gostou da ferramenta? Vai ser útil pra você? Já existe algo que faça isso? Comente! :D</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2016/03/how-many-hours.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hmh - How many hours?&lt;/code&gt; foi uma ferramenta que eu resolvi criar, pois precisava fazer alguns cálculos com horas, mas não achei nada que eu pudesse usar, assim, “a toque de caixa”.&lt;br&gt;O projeto está no GitHub, &lt;a href=&quot;https://github.com/fdaciuk/hmh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;nesse link&lt;/a&gt;. Quer saber como foi desenvolvido, desde a ideia, os testes até a publicação? Então vem comigo que eu te mostro :D&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="nodejs" scheme="https://blog.da2k.com.br/tags/nodejs/"/>
    
      <category term="cli" scheme="https://blog.da2k.com.br/tags/cli/"/>
    
      <category term="hmh" scheme="https://blog.da2k.com.br/tags/hmh/"/>
    
  </entry>
  
  <entry>
    <title>Retrospectiva 2015</title>
    <link href="https://blog.da2k.com.br/2016/01/01/retrospectiva-2015/"/>
    <id>https://blog.da2k.com.br/2016/01/01/retrospectiva-2015/</id>
    <published>2016-01-01T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.874Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2016/01/retrospectiva-2015.png" alt="Retrospectiva 2015"></p><p>Vi muitas pessoas comemorando, outras reclamando de como foi esse ano de 2015 para elas. Quer saber como foi o meu? Vem comigo que eu te conto! :D</p><a id="more"></a><p>Em resumo: 2015 pra mim foi <strong>sensacional!</strong> Em praticamente todos os sentidos!</p><h2 id="1-post-por-dia"><a href="#1-post-por-dia" class="headerlink" title="1 post por dia"></a>1 post por dia</h2><p>Você deve lembrar do desafio que eu lancei publicamente a mim mesmo - e a quem quisesse acompanhar - no último dia do ano de 2014, não?</p><p>Foi o de escrever <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">um post por dia</a>, e compartilhar usando a hashtag <strong>#1postperday</strong>. Isso mesmo! E foi um dsafio e tanto :D</p><p>O que mais me deixou feliz com isso, foi ver a quantidade de devs que também se animaram a criar seus blogs e escrever mais conteúdo de qualidade em pt-br, uma vez por dia, uma vez por semana, uma vez por mês, ou só um post no ano. Não importa. O importante é que a meta principal de alcançar muitas pessoas foi cumprida :D</p><p>Recebi muitos feedbacks positivos por causa do #1postperday. O <a href="http://willianjusten.com.br/" target="_blank" rel="noopener">Willian Justen</a> compartilhou conteúdos sensacionais no seu blog sobre vários assuntos; o <a href="http://rcdevlabs.github.io/" target="_blank" rel="noopener">Rômulo Zoch</a> deu dicas animais de NodeJS, Ionic, entre várias outras coisas; <a href="http://nandomoreira.me/" target="_blank" rel="noopener">Fernando Moreira</a>, <a href="http://www.raphaelfabeni.com.br/" target="_blank" rel="noopener">Raphael Fabeni</a>, e vários outros caras feras - que eu não conseguiria citar todos aqui - compartilhando o seu conhecimento com a comunidade, mostrando que temos ótimos profissionais aqui no Brasil \o/</p><p>O <a href="http://www.felipefialho.com/" target="_blank" rel="noopener">Felipe Fialho</a> ainda criou <a href="https://github.com/LFeh/poste-mais" target="_blank" rel="noopener">um repositório</a> para que qualquer pessoa pudesse colaborar com assuntos para os próximos posts, que inclusive você pode continuar abrindo issues por lá, que os posts continuarão a ser escritos :D</p><p>Enfim, obviamente que eu não consegui escrever o ano todo. Consegui fazer, em média 70 posts, depois começou a ficar complicado :P</p><p>Mas fiquei muito feliz mesmo com o resultado positivo que isso trouxe para toda a comunidade de desenvolvimento web brasileira :D</p><p>E esse pequeno desafio trouxe frutos muito legais:</p><h2 id="Projetos-Open-Source"><a href="#Projetos-Open-Source" class="headerlink" title="Projetos Open Source"></a>Projetos Open Source</h2><p>A partir dos posts, para ter ideias de conteúdo, acabei criando alguns projetos open source bastante simples, para exemplificar nos posts, mas que foram tomando corpo e, pelo que parece, foi e está sendo útil para várias pessoas :)</p><p>Um deles é o <a href="https://github.com/fdaciuk/ajax/" target="_blank" rel="noopener">ajax.js</a>, que é uma abstração do objeto XMLHttpRequest do Javascript, usando promises em uma implementação em JS puro, sem o uso de bibliotecas. Foi um aprendizado gigante pra mim poder fazer isso, com certeza isso melhorou muito minhas skills em JS :)</p><p>E tudo começou com <a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">esse post</a>, que é um primeiro de <a href="https://blog.da2k.com.br/tags/ajax/">toda uma série</a>, mostrando como a lib foi montada, inclusive mostrando a aplicação de testes :)</p><p>Um outro projeto bastante simples foi o <a href="https://github.com/fdaciuk/hoost" target="_blank" rel="noopener">hoost</a>, uma ferramenta de linha de comando que adiciona, edita, remove e lista os virtual hosts no arquivo <code>/etc/hosts</code>. Apesar de simples, várias pessoas tem usado, e algumas colaborado com o projeto. Inclusive, a implementação para que o <code>hoost</code> funcionasse no Windows veio de um Pull Request enviado por um gringo :)</p><p>E ainda tem coisas a fazer nesse projeto! Já tenho algumas ideias legais de implementação para adicionar as entradas automaticamente nos arquivos de configuração do Apache e nginx xD</p><p>Enfim, foi um ano de muito aprendizado, pois, para escrever sobre algum assunto, eu precisava pesquisar para não escrever besteiras, e com isso eu pude aprender muito. Recomendo a todos que estejam dispostos a aprender mais sobre qualquer coisa, e que ainda não tem blog, que crie um, e comece a escrever! Existem algumas ferramentas que facilitam muito a criação de um blog, como o <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a> por exemplo. Escrevi sobre ele <a href="https://blog.da2k.com.br/2014/01/05/hexo-criando-um-blog-ao-estilo-miojo/">aqui</a>. Veja como é fácil ter um blog rodando em apenas 3 minutos :D</p><h2 id="Cursos-Javascript-Ninja-e-Git-e-GitHub-Ninja"><a href="#Cursos-Javascript-Ninja-e-Git-e-GitHub-Ninja" class="headerlink" title="Cursos Javascript Ninja e Git e GitHub Ninja"></a>Cursos Javascript Ninja e Git e GitHub Ninja</h2><p>Ainda por causa do #1postperday, eu consegui colocar em prática algo que eu já queria fazer há muito tempo: criar um curso de Javascript que ensinasse desde a pessoa que nunca tinha programado na vida, como aqueles que já estavam estudando JS a algum tempo, mas não conseguiam evoluir no aprendizado.</p><p>Assim nasceu o curso <a href="https://blog.da2k.com.br/curso-javascript-ninja/"><strong>Javascript Ninja!</strong></a></p><p>E eu tenho recebido ótimos feedbacks com relação ao curso. Pelo visto tem funcionado xD</p><p>Percebi também a necessidade que algumas pessoas tinham em aprender a utilizar Git e GitHub para uso no dia a dia do trabalho, ainda que para coisas simples. Pensando nisso, criei também o curso <a href="https://blog.da2k.com.br/curso-git-e-github-ninja/"><strong>Git e GitHub Ninja</strong></a>, para mostrar o básico de como utilizar o Git, e como aproveitar o melhor do GitHub para trabalhar em equipe :D</p><p>Ministrar <a href="https://blog.da2k.com.br/cursos/">cursos</a> era algo que eu já queria fazer a um tempo, mas nunca tinha tirado a ideia do papel. Nesse ano de 2015 eu resolvi me mexer e fazer acontecer! E tem dado ótimos resultados :D</p><h2 id="Eventos"><a href="#Eventos" class="headerlink" title="Eventos"></a>Eventos</h2><p>Outro ponto forte de 2015 foram os eventos que eu tive o prazer de participar. Tivemos alguns meetups locais aqui em Joinville, sobre WordPress, frontend, e desenvolvimento de software em geral.</p><p>Pude participar pela primeira vez da BrazilJS, e foi uma das melhores experiências que eu tive em eventos! Com certeza, em 2016 estarei lá novamente :D</p><p>Não só o evento foi sensacional, como também conhecer pessoalmente pessoas que eu só conversava pelos grupos do Facebook, chats e fóruns.</p><p>Posso dizer que eventos foram o ponto alto do meu ano: <em>WordCamps</em>, <em>Frontins</em>; o contato e networking com pessoas apaixonadas pelo que fazem me fizeram sentir em casa em cada um deles.</p><p>Tive oportunidade de <a href="https://github.com/fdaciuk/talks" target="_blank" rel="noopener">palestrar em alguns</a> também :D</p><p>Foi muito bom conhecer pessoalmente caras como <a href="http://willianjusten.com.br/" target="_blank" rel="noopener">Willian Justen</a>, <a href="http://udgwebdev.com/" target="_blank" rel="noopener">Caio Ribeiro</a>, <a href="http://jaydson.org/" target="_blank" rel="noopener">Jaidson Gomes</a>, <a href="http://jugoncalv.es/" target="_blank" rel="noopener">Ju Gonçalves</a>, <a href="http://eduardomatos.me/" target="_blank" rel="noopener">Eduardo Matos</a>, <a href="http://raphamorim.com/" target="_blank" rel="noopener">Rafael Amorim</a>, <a href="http://www.raphaelfabeni.com.br/" target="_blank" rel="noopener">Fabeni</a>, <a href="https://blog.henriquesilver.io/" target="_blank" rel="noopener">Henrique Silvério</a>, <a href="http://felquis.com/" target="_blank" rel="noopener">Felquis</a>, <a href="http://pedropolisenso.com/" target="_blank" rel="noopener">Pedro Polisenso</a>, entre tantos outros; sem contar as pessoas que eu já conhecia e pude rever, como: <a href="http://felipenmoura.com/" target="_blank" rel="noopener">Filipe Moura</a>, <a href="http://jcemer.com/" target="_blank" rel="noopener">Jean Emer</a>, <a href="http://talitapagani.com/" target="_blank" rel="noopener">Talita Pagani</a>, <a href="http://diogo.nu/" target="_blank" rel="noopener">Diogo Moretti</a>, <a href="https://lucas.ninja/" target="_blank" rel="noopener">Lucas</a> e a galera do WP: <a href="http://www.rafaelfunchal.com.br/" target="_blank" rel="noopener">Rafael Funchal</a>, <a href="https://claudiosmweb.com/" target="_blank" rel="noopener">Claudio Sanches</a>, <a href="http://deblynprado.com/" target="_blank" rel="noopener">Deblyn</a>, <a href="http://valeriosouza.com.br/" target="_blank" rel="noopener">Valério Souza</a>, <a href="http://www.gugaalves.net/" target="_blank" rel="noopener">Guga Alves</a>; conheci também pessoalmente alguns dos alunos que fazem meus cursos, como o <a href="https://github.com/theandersonn" target="_blank" rel="noopener">Anderson Nascimento</a>, o <a href="https://github.com/matheuswd" target="_blank" rel="noopener">Matheus Martins</a>, o <a href="https://github.com/DWoonD" target="_blank" rel="noopener">Willian Santos</a>; entre tantos outros que eu poderia ficar dois dias escrevendo, e ainda assim não conseguiria lembrar de todos aqui para citar, mas que foi um prazer enorme conhecê-los e revê-los :D</p><h2 id="Profissional"><a href="#Profissional" class="headerlink" title="Profissional"></a>Profissional</h2><p>Comecei o ano trabalhando como Frontend Engineer na <a href="https://contaazul.com/" target="_blank" rel="noopener">ContaAzul</a>, onde pude aprender muito mesmo, e crescer tanto pessoalmente, como profissionalmente. Lá eu vi realmente que valores são levados a sério, vi pessoas comprometidas trabalhando juntas por um único ideal de fazer o cliente feliz! Lá dentro eu tive aprendizado gigantesco!</p><p>Só saí de lá quando recebi uma oportunidade de trabalhar com algo que estava alinhado profissionalmente com os meus objetivos pessoais. Foi quando o <a href="http://luanmuniz.com.br/" target="_blank" rel="noopener">Luan Muniz</a> me apresentou o <a href="http://zimp.me/" target="_blank" rel="noopener">Zimp</a>, onde estou trabalhando hoje como Full Stack Developer.</p><p>E como o trabalho é remoto, isso acaba meio que “obrigando” a todos do time a terem uma comunicação frequente, para manter o alinhamento das entregas e tudo sair o mais próximo possível do esperado, o que faz com que todos saibam exatamente o que está acontecendo em todas as áreas da empresa, unindo forças para que o produto seja o melhor possível em todos os sentidos.</p><p>Fiquem ligados que, para 2016, estamos preparando algo animal para o Zimp :D</p><h2 id="Finalmente"><a href="#Finalmente" class="headerlink" title="Finalmente"></a>Finalmente</h2><p>Enfim, 2015 foi animal! E com certeza 2016 será 1000x melhor! Obrigado a todos que fizeram parte desse ano! Ano que vem espero conhecer muito mais pessoas, participar de muito mais eventos, e ver a comunidade crescer e evoluir muito mais!</p><p>E 2016 teremos muitas novidades! Não vou fazer #1postperday, mas vou procurar escrever mais, e de forma mais uniforme xD</p><p>Feliz ano novo! \o/</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2016/01/retrospectiva-2015.png&quot; alt=&quot;Retrospectiva 2015&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vi muitas pessoas comemorando, outras reclamando de como foi esse ano de 2015 para elas. Quer saber como foi o meu? Vem comigo que eu te conto! :D&lt;/p&gt;
    
    </summary>
    
      <category term="retrospectiva" scheme="https://blog.da2k.com.br/categories/retrospectiva/"/>
    
    
  </entry>
  
  <entry>
    <title>Javascript - O operador +</title>
    <link href="https://blog.da2k.com.br/2015/06/25/javascript-o-operador-plus/"/>
    <id>https://blog.da2k.com.br/2015/06/25/javascript-o-operador-plus/</id>
    <published>2015-06-25T21:07:32.000Z</published>
    <updated>2025-05-12T12:40:00.866Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/06/plus-operator.png" alt=""></p><p><em>Operador “+”? O que tem de “mais” nisso - além do próprio operador?</em> Vou te mostrar que esse operador pode te surpreender, dependendo da forma que você o usa. Quer ver? Vem comigo que eu te mostro! :)</p><a id="more"></a><p>Todo mundo que conhece um pouquinho de Javascript, sabe que o operador <strong>+</strong> serve para ao menos duas coisas: somar números e concatenar strings!</p><p>Mas você pode fazer muito mais com ele! Vou te mostrar todos os usos possíveis :)</p><h2 id="Somar-numeros"><a href="#Somar-numeros" class="headerlink" title="Somar números"></a>Somar números</h2><p>Quando você usa o operador <strong>+</strong> com dois operandos números, o JS efetua uma soma:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10</span> + <span class="number">10</span>; <span class="comment">// 20</span></span><br></pre></td></tr></table></figure><p>Executando esse código no console, você tem <code>20</code> como resultado.</p><p><em>Tá, e daí? Isso eu já sabia!</em></p><p>Calma que tem mais!</p><h2 id="Concatenacao"><a href="#Concatenacao" class="headerlink" title="Concatenação"></a>Concatenação</h2><p>Quando você usa o operador <strong>+</strong> com dois operandos strings, ou um número e uma string, é feita uma <strong>concatenação</strong>. O interpretador do JS irá converter o valor que não é string para <code>String</code>, e fazer a concatenação:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'10'</span> + <span class="number">10</span>; <span class="comment">// "1010"</span></span><br><span class="line"><span class="number">10</span> + <span class="string">'kg'</span>; <span class="comment">// "10kg"</span></span><br><span class="line"><span class="string">'Java'</span> + <span class="string">'Script'</span>; <span class="comment">// "JavaScript"</span></span><br></pre></td></tr></table></figure><p>Experimente executar os códigos acima no seu console.</p><p><em>Nenhuma novidade ainda :(</em></p><p>Ainda não acabou ;)</p><h2 id="Pre-e-pos-incremento"><a href="#Pre-e-pos-incremento" class="headerlink" title="Pré e pós incremento"></a>Pré e pós incremento</h2><p>Usando o <strong>+</strong> como um operador unário, você pode fazer pós ou pré-incremento em valores de variáveis. Vou exemplificar:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> number = <span class="number">10</span>;</span><br><span class="line">number++; <span class="comment">// 10</span></span><br><span class="line">number; <span class="comment">// 11</span></span><br></pre></td></tr></table></figure><p>O que aconteceu acima foi o seguinte: declaramos uma variável <code>number</code> com o valor <code>10</code>. Ao usar o operador de <strong>pós-incremento</strong> <code>++</code>, a variável é avalidada, devolvendo o seu valor atual, e logo após, e feita a atribuição de todo o valor já existente na variável + 1.</p><p>Por isso que, chamando <code>number++</code>, o retorno é <code>10</code>, mas na próxima chamada de <code>number</code>, o valor é <code>11</code>.</p><p>Podemos fazer també <strong>pré-incremento</strong>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> number = <span class="number">10</span>;</span><br><span class="line">++number; <span class="comment">// 11</span></span><br><span class="line">number; <span class="comment">// 11</span></span><br></pre></td></tr></table></figure><p>Usando o operador de <strong>pré-incremento</strong> <code>++</code>, a atribuição é feita primeiro, e então a variável é avaliada. Por isso, na chamada <code>++number</code>, o valor retornado já não é o valor inicial de <code>10</code>, mas sim <code>11</code>.</p><p>Lembrando que esses operadores devem ser usados com cautela, pois causam efeito colateral no valor das varáveis, fazendo uma atribuição implícita.</p><h2 id="Atribuicao-abreviada"><a href="#Atribuicao-abreviada" class="headerlink" title="Atribuição abreviada"></a>Atribuição abreviada</h2><p>Além dos operadores de pré e pós incremento, você ainda pode usar o operador de soma com atribuição abreviada, para somar valores diferentes de 1:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> number = <span class="number">10</span>;</span><br><span class="line">number += <span class="number">5</span>;</span><br><span class="line">number; <span class="comment">// 15</span></span><br></pre></td></tr></table></figure><p>Faz basicamente o que os exemplos anteriores faziam, com a diferença que você pode escolher o valor que será atribuído, e ainda deixar explícito que uma atribuição está sendo feita ;)</p><p>Mas ainda tem mais :D</p><h2 id="Conversao-de-valores-para-numero"><a href="#Conversao-de-valores-para-numero" class="headerlink" title="Conversão de valores para número"></a>Conversão de valores para número</h2><p>Você ainda pode usar o operador <strong>+</strong> para converter de strings numéricas para números:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typeof</span> <span class="string">'10'</span>; <span class="comment">// "string"</span></span><br><span class="line"><span class="keyword">typeof</span> +<span class="string">'10'</span>; <span class="comment">// "number"</span></span><br><span class="line"><span class="string">'10'</span> + <span class="number">10</span>; <span class="comment">// "1010"</span></span><br><span class="line">+<span class="string">'10'</span> + <span class="number">10</span>; <span class="comment">// 20</span></span><br><span class="line"><span class="number">10</span> + +<span class="string">'10'</span>; <span class="comment">// 20</span></span><br></pre></td></tr></table></figure><p>Perceba que, usando o operador <code>+</code> como <strong>unário</strong> antes de qualquer string numérica, essa string é convertida para número, e assim você consegue efetuar operações com números normalmente ;)</p><p>Usando o operador <strong>+</strong> dessa forma, tem o mesmo efeito de usar o objeto <code>Number</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Number</span>(<span class="string">'10'</span>) + <span class="number">10</span>; <span class="comment">// 20</span></span><br></pre></td></tr></table></figure><p>Bom, esses são alguns usos do operador <strong>+</strong>. Você já conhecia todos? Ficou alguma dúvida? Comente!</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/06/plus-operator.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Operador “+”? O que tem de “mais” nisso - além do próprio operador?&lt;/em&gt; Vou te mostrar que esse operador pode te surpreender, dependendo da forma que você o usa. Quer ver? Vem comigo que eu te mostro! :)&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
  </entry>
  
  <entry>
    <title>Javascript - Criando um módulo Ajax com Promises - Parte 5</title>
    <link href="https://blog.da2k.com.br/2015/03/22/javascript-criando-um-modulo-ajax-com-promises-parte-5/"/>
    <id>https://blog.da2k.com.br/2015/03/22/javascript-criando-um-modulo-ajax-com-promises-parte-5/</id>
    <published>2015-03-22T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.862Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises5.png" alt=""></p><p>Seguindo com <a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">nossa série</a>, vamos agora fazer funcionar o método <strong>POST</strong> do nosso módulo <strong>Ajax</strong>!</p><a id="more"></a><h2 id="Testando-o-metodo-POST"><a href="#Testando-o-metodo-POST" class="headerlink" title="Testando o método POST"></a>Testando o método POST</h2><p>No último artigo, criamos um <code>describe()</code> para testar o método <code>get()</code>. Faremos o mesmo agora para o método <code>post()</code>. No arquivo <code>tests/test.ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">describe( <span class="string">'Test `post` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  it( <span class="string">'Should return an object'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">    ajax.post( <span class="string">'http://localhost:3000/api/user/joao'</span> ).done(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">      response.should.be.an( <span class="string">'object'</span> );</span><br><span class="line">      done();</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>O método <code>post()</code> na nossa API de testes retorna um objeto com os dados do usuário passado. Estamos chamando os dados do usuário <code>joao</code>, então, nosso primeiro teste, é verificar se a requisição nos retorna um objeto.</p><p>Obviamente, o teste não passa, pois ainda não implementamos a funcionalidade para o método <code>post()</code> no nosso módulo. Sem mais delongas, vamos fazer isso agora mesmo. No arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"> url </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">  xhr.open( <span class="string">'POST'</span>, url || <span class="string">''</span>, <span class="literal">true</span> );</span><br><span class="line">  xhr.addEventListener( <span class="string">'readystatechange'</span>, $private.handleReadyStateChange, <span class="literal">false</span> );</span><br><span class="line">  xhr.send();</span><br><span class="line">  <span class="keyword">return</span> $private.promises();</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>O método post na nossa API recebe via URL o parâmetro <code>slug</code>, onde iremos fazer algo com os dados desse usuário. No exemplo, nós simplesmente retornamos os dados, mas em uma API real, provavelmente iremos alterar esses dados, ou tratar de alguma forma.</p><p>Por ser simples, a implementação no nosso módulo é basicamente a mesma do método <code>get()</code>, com a diferença do método <code>open()</code>, onde passamos o atributo <code>POST</code>, ao invés de <code>GET</code>.</p><p>Agora nosso teste passa! Estamos com todos os testes verdes, mas temos código repetido. Já sabe o que temos que fazer né? Isso mesmo: <strong style="color: blue">REFACTORY!</strong></p><p>Esse é o momento em que deixamos nosso código um pouco melhor, mais legível, muitas vezes removendo código - pois menos é mais :D - mas sempre mantendo os testes passando. Não podemos implementar nada novo nesse momento, apenas melhorar o que já temos :)</p><p>Vamos então fazer o <em>refactory</em>. Criaremos um novo método para envolver o código repetido, e passaremos por parâmetro somente o tipo e a URL. No arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$private.XHRConnection = <span class="function"><span class="keyword">function</span> <span class="title">XHRConnection</span>(<span class="params"> type, url </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">  xhr.open( type, url || <span class="string">''</span>, <span class="literal">true</span> );</span><br><span class="line">  xhr.addEventListener( <span class="string">'readystatechange'</span>, $private.handleReadyStateChange, <span class="literal">false</span> );</span><br><span class="line">  xhr.send();</span><br><span class="line">  <span class="keyword">return</span> $private.promises();</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>E os nossos métodos <code>get()</code> e <code>post()</code> agora ficarão assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"> url </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> $private.XHRConnection( <span class="string">'GET'</span>, url );</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">$public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"> url </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> $private.XHRConnection( <span class="string">'POST'</span>, url );</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Se executarmos nossos testes, veremos que tudo continua passando lindamente! <em>Refactory</em> executado com sucesso \o/</p><p>Como disse acima, na maioria dos casos, os métodos <code>post</code>, <code>put</code> e <code>delete</code> podem receber os parâmetros implicitamente, ao invés de enviar via URL. Vamos então preparar nossa API para receber um <strong>POST</strong> através da URL <code>http://localhost:3000/user</code>, e passar o parâmetro implicitamente.</p><p>Primeiro vamos precisar instalar o <code>body-parser</code>, que vai parsear os dados que recebermos via <strong>POST</strong> em <code>req.body</code>. Instale com o comando abaixo no seu terminal:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev body-parser</span><br></pre></td></tr></table></figure><p>Agora, vamos adicionar o <code>body-parser</code> à nossa API. No início do nosso arquivo <code>api/app.js</code>, vamos adicionar o <code>body-parser</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> bodyParser = <span class="built_in">require</span>( <span class="string">'body-parser'</span> );</span><br></pre></td></tr></table></figure><p>Agora, antes da chamada onde setamos o header <code>res.setHeader( &#39;Access-Control-Allow-Origin&#39;, &#39;*&#39; );</code>, vamos dizer ao <code>connect</code> que ele deve usar o <em>middleware</em> do <code>bodyParser</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">app.use( bodyParser.urlencoded(&#123; <span class="attr">extended</span>: <span class="literal">false</span> &#125;) );</span><br><span class="line">app.use( bodyParser.json() );</span><br></pre></td></tr></table></figure><p>Vamos também fazer uma pequena alteração na função <code>postResponse()</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">postRequest</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> user = req.params.slug || req.body.slug;</span><br><span class="line">  res.setHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/json'</span> );</span><br><span class="line">  res.end( <span class="built_in">JSON</span>.stringify( users[ user ] ) );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Essa alteração é para que possamos obter dados vindo tanto da URL, com <code>req.params.slug</code>, como os dados enviados no corpo da requisição, com <code>req.body.slug</code>. Como vamos sempre usar um ou outro, podemos tratar dessa forma, com <code>||</code>.</p><p>E por fim, vamos criar mais um <em>endpoint</em> para nossa nova requisição à <code>http://localhost:3000/user</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">router.post( <span class="string">'/api/user'</span>, postRequest );</span><br><span class="line">router.post( <span class="string">'/api/user/:slug'</span>, postRequest );</span><br></pre></td></tr></table></figure><p>A linha <code>2</code>, já existe na nossa API, somente adicionamos a linha <code>1</code>. Vamos testar nossa API com o <strong>Postman</strong>, e verificar se o request retorna a requisição que desejamos:</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/request-post-data-implicit.png" alt=""></p><p>Pronto! Tudo funciona corretamente! Só precisamos enviar o <em>header</em> <code>x-www-form-urlencoded</code> na nossa requisição :D</p><p>Se ficou em dúvida de como o arquivo deve ficar, consulte o <a href="https://github.com/fdaciuk/ajax" target="_blank" rel="noopener">repositório onde estamos desenvolvendo nosso módulo</a>.</p><p>Mas para não ficarmos só no teste manual, vamos adicionar mais um teste no nosso arquivo <code>tests/test.ajax.js</code>, para essa URL:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should return data about `joao`'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  ajax.post( <span class="string">'http://localhost:3000/api/user'</span>, <span class="string">'slug=joao'</span> ).done(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log( response );</span><br><span class="line">    response.name.should.be.equal( <span class="string">'João da Silva'</span> );</span><br><span class="line">    done();</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>A novidade aqui é que passamos mais um parâmetro no método <code>post()</code>: os dados que serão enviados ao servidor, em formato de <em>query string</em>. Passamos o parâmetro <code>slug</code>, que é o que nossa API espera, com o <em>slug</em> do usuário que queremos os dados de volta. Para passar mais dados, você pode usar o formato: <code>dado1=valor1&amp;dado2=valor2&amp;dado3=valor3</code>.</p><p>Vamos agora implementar essa funcionalidade em <code>src/ajax.js</code>. Primeiro, passamos o parâmetro para o método <code>post()</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"> url, data </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> $private.XHRConnection( <span class="string">'POST'</span>, url, data );</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Agora vamos alterar o método da conexão, para receber os dados e enviar ao servidor, com o <em>header</em> correto:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">$private.XHRConnection = <span class="function"><span class="keyword">function</span> <span class="title">XHRConnection</span>(<span class="params"> type, url, data </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">  xhr.open( type, url || <span class="string">''</span>, <span class="literal">true</span> );</span><br><span class="line">  xhr.setRequestHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/x-www-form-urlencoded'</span> );</span><br><span class="line">  xhr.addEventListener( <span class="string">'readystatechange'</span>, $private.handleReadyStateChange, <span class="literal">false</span> );</span><br><span class="line">  xhr.send( data );</span><br><span class="line">  <span class="keyword">return</span> $private.promises();</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Passamos o parâmetro <code>data</code> no método, que será passado para <code>xhr.send()</code>, e adicionamos o <em>header</em> <code>application/x-www-form-urlencoded</code>.</p><p>Agora nosso método faz requisições <strong>GET</strong> e <strong>POST</strong>, e todos os testes estão passando! o/</p><p>Os métodos <code>put()</code> e <code>delete()</code> são praticamente o <code>post()</code>, somente mudando para o verbo correto - <code>PUT</code> e <code>DELETE</code>.</p><p>Podemos ainda melhorar o tipo de envio de dados: ao invés de passar uma <em>query string</em>, poderíamos passar um objeto e, no módulo, tratar esses dados, convertendo para <em>query string</em> antes de fazer o envio.</p><p>Como você pode ver, tem muitas coisas que podemos fazer para melhorar: o envio dos dados, <em>headers</em> dinâmicos, credenciais para validação no servidor (usuário e senha), até que todos os métodos do objeto <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest" target="_blank" rel="noopener">XMLHttpRequest</a> estejam cobertos. A série acaba por aqui, mas vou fazendo essas implementaçôes aos poucos! Se quiser acompanhar, dê um <strong>watch</strong> no repositório: <a href="https://github.com/fdaciuk/ajax" target="_blank" rel="noopener">https://github.com/fdaciuk/ajax</a></p><p>Dúvidas? Comente!</p><p>Até o próximo o/</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises5.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Seguindo com &lt;a href=&quot;https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/&quot;&gt;nossa série&lt;/a&gt;, vamos agora fazer funcionar o método &lt;strong&gt;POST&lt;/strong&gt; do nosso módulo &lt;strong&gt;Ajax&lt;/strong&gt;!&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="ajax" scheme="https://blog.da2k.com.br/tags/ajax/"/>
    
  </entry>
  
  <entry>
    <title>Criando uma ferramenta de CLI com NodeJS</title>
    <link href="https://blog.da2k.com.br/2015/03/20/criando-uma-ferramenta-de-cli-com-nodejs/"/>
    <id>https://blog.da2k.com.br/2015/03/20/criando-uma-ferramenta-de-cli-com-nodejs/</id>
    <published>2015-03-20T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.850Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/nodejs-cli.png" alt=""></p><p>Ferramentas de linha de comando ajudam quando você precisa executar tarefas mais rapidamente. Que tal aprender a criar você mesmo a sua? E em <strong>NodeJS</strong>! E ainda disponibilizar no <strong>NPMJS</strong>! Ficou curioso? Vem que eu te mostro como faz ;)</p><a id="more"></a><h2 id="O-que-e-uma-CLI"><a href="#O-que-e-uma-CLI" class="headerlink" title="O que é uma CLI?"></a>O que é uma CLI?</h2><p><strong>CLI</strong> significa <em>Command Line Interface</em>, ou seja, é uma ferramenta que disponibiliza uma interface de linha de comando para que você possa executar alguns comandos específicos no terminal. Normalmente essas ferramentas são criadas utilizando <em>shell script</em>, mas nós vamos criar a nossa com Javascript :D</p><p><em>Antes de começar, que tal mostrar alguns exemplos de <strong>CLI</strong></em>?</p><p><a href="http://gulpjs.com/" target="_blank" rel="noopener"><strong>Gulp</strong></a>, <a href="http://gruntjs.com/" target="_blank" rel="noopener"><strong>Grunt</strong></a>, <a href="http://expressjs.com/" target="_blank" rel="noopener"><strong>Express</strong></a>, <a href="http://mochajs.org/" target="_blank" rel="noopener"><strong>Mocha</strong></a>, e inclusive o próprio <a href="https://nodejs.org/" target="_blank" rel="noopener"><strong>NodeJS</strong></a> e <a href="https://www.npmjs.com/" target="_blank" rel="noopener"><strong>NPM</strong></a> são ótimos exemplos de <strong>CLI</strong>. Essas ferramentas de <strong>CLI</strong> criadas em <strong>NodeJS</strong> normalmente estão disponíveis para baixar no <a href="https://www.npmjs.com/" target="_blank" rel="noopener">https://www.npmjs.com/</a>, onde você instala com o comando <code>npm i -g nome-da-ferramenta</code>.</p><p>Quando você instala um módulo do <strong>Node</strong> globalmente, usando o <code>-g</code>, é porque essa ferramenta normalmente disponibiliza essa interface de linha de comando, onde você não precisa depender do comando <code>node nome-da-ferramenta</code> para executá-la, e sim poder usar o próprio nome da ferramenta como comando.</p><p>Por exemplo: como você faz para executar uma tarefa do <strong>Gulp</strong>? Você executa <code>gulp nome-da-task</code>, sem precisar do comando <code>node</code>! Isso é uma <strong>CLI</strong> :D</p><h2 id="Como-faz-entao"><a href="#Como-faz-entao" class="headerlink" title="Como faz então?"></a>Como faz então?</h2><p>Vamos criar uma ferramenta bastante simples: uma calculadora que faz a soma entre dois números passados como parâmetro. A primeira coisa é escolher um nome para a ferramenta, - <em>vixxxxxx</em> - pois esse nome precisa estar disponível no NPMJS :)</p><p>Acho que essa é a parte mais difícil, haha :D</p><p>Não conheço nenhuma ferramenta que verifique se um nome está disponível no NPMJS - inclusive, isso seria uma ideia bem útil de CLI ;) - então vamos verificar manualmente se tem algum nome disponível, chutando mesmo:</p><p>Acesse <a href="https://www.npmjs.com/package/" target="_blank" rel="noopener">https://www.npmjs.com/package/</a>, e coloque um nome após a barra. Se ele estiver disponível, você verá uma página de <code>not found</code> :)</p><p>Nossa <strong>CLI</strong> se chamará <code>calculatr</code>, e será usada da seguinte forma: usaremos no terminal o comando para somar dois números:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">calculatr sum 2 3</span><br></pre></td></tr></table></figure><p>Que nos dará o resultado <code>5</code>! Bem inútil, mas vai servir para você ver como funciona uma <strong>CLI</strong> :D</p><p><strong>Observação:</strong> existem muitos pacotes no NPMJS, alguns indispensáveis, outros bastante inúteis. Então lembre-se que você sempre terá a opção de <strong>despublicar</strong> um pacote, se você estiver fazendo somente testes para ver como tudo funciona por lá. Assim nós ajudamos ao próximo e a nós mesmos, não deixando no NPMJS coisas desatualizadas e que não sirvam para nada ;)</p><p>Agora que sabemos como será a interface do nosso projeto, vamos ver como criar a ferramenta.</p><h2 id="Primeiros-passos"><a href="#Primeiros-passos" class="headerlink" title="Primeiros passos"></a>Primeiros passos</h2><p>O passo inicial é criar um diretório separado para o projeto. A estrutura será bastante simples: só precisaremos de um diretório chamado <code>calculatr/</code> e, dentro dele, um arquivo com qualquer nome. Vamos chamar de <code>calculatr.js</code> :)</p><p>Precisaremos também de um <code>package.json</code> com algumas informações para o nosso módulo.</p><p>Em artigos anteriores, mostrei que você poderia sempre criar o seu <code>package.json</code> com o comando <code>echo &quot;{}&quot; &gt; package.json</code>, que imprimiria dentro do arquivo somente um “abre e fecha chaves”, que é o mínimo que precisamos quando estamos usando o <strong>Node</strong> com um <em>task runner</em>, por exemplo, onde o <code>package.json</code> será usado somente para gerenciamento de pacotes.</p><p>Agora, nós vamos criar nosso próprio módulo <strong>NodeJS</strong>, então o <code>package.json</code> precisa de uma atenção especial :)</p><h2 id="Criando-o-package-json"><a href="#Criando-o-package-json" class="headerlink" title="Criando o package.json"></a>Criando o <code>package.json</code></h2><p>Para criar o <code>package.json</code>, você pode usar o comando <code>npm init</code>, e então responder algumas perguntas para criar seu módulo. A primeira pergunta é sobre o nome do módulo. Por <em>default</em>, NPM vai te sugerir o nome do diretório atual, que normalmente é o nome do projeto. Vamos manter (se estive como <code>calculatr</code>).</p><p>A próxima pergunta é sobre a versão. Estamos começando agora, então vamos deixar com a versão <code>0.0.1</code>. Daqui a pouco vou explicar melhor sobre como funcionam as versões ;)</p><p>Por enquanto, digite <code>0.0.1</code> e dê enter.</p><p>Agora é pedido uma descrição sobre o projeto. Essa descrição aparecerá no site do NPMJS, então capriche ;)<br>Vamos deixar algo como:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CLI Calculator</span><br></pre></td></tr></table></figure><p>Depois, ele pede o <code>entrypoint</code>. Esse parâmetro referencia o arquivo principal, ou o ponto de entrada da nossa aplicação. No nosso caso, esse arquivo é o <code>calculatr.js</code>.</p><p>O próximo é <code>test command</code>. Esse será o comando que você irá utilizar para testar seu código. Vamos utilizar o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">istanbul cover _mocha -- -R spec</span><br></pre></td></tr></table></figure><p>Utilizaremos o <a href="https://blog.da2k.com.br/2015/01/07/code-coverage-em-javascript/"><code>istanbul</code> para coverage</a> e o <a href="https://blog.da2k.com.br/2015/01/06/pensando-tdd-com-javascript/"><code>mocha</code> para os testes</a>. Lembre-se de ter esses dois pacotes instalados globalmente. Se não tiver, execute no seu terminal:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -g istanbul mocha</span><br></pre></td></tr></table></figure><p>A próxima pergunta é sobre o repositório no Github. Se você ainda não criou o repositório para esse projeto, faça-o e entre com a URL. Se quiser fazer depois, não há problemas. Quando você configurar o <code>git</code> para esse projeto e rodar <code>npm init</code> novamente, o seu <code>package.json</code> será atualizado com essas informações :)</p><p>A licença, você pode escolher uma que esteja de acordo com o formato que você irá disponibilizar sua ferramenta. Normalmente usa-se <code>MIT</code>, ou <code>GPLv2</code>, <code>v3</code>. Se tiver dúvidas quanto à licença, pode escolher uma [por aqui] (<a href="http://choosealicense.com/)" target="_blank" rel="noopener">http://choosealicense.com/)</a>.</p><p>Se tudo der certo, você terá um <code>package.json</code> preenchido!</p><p>Mas, como estamos criando uma <strong>ferramenta de CLI</strong>, precisamos adicionar mais algumas entradas. Edite seu <code>package.json</code>, e adicione:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">"preferGlobal": true,</span><br><span class="line">"bin": &#123;</span><br><span class="line">  "calculatr": "calculatr.js"</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>No site do NPMJS, é mostrado o comando de instalação do módulo. O <code>preferGlobal</code> diz ao NPM que esse módulo deve ser instalado globalmente. Logo, no site do NPMJS irá aparecer o seguinte comando para instalação do móulo:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g calculatr</span><br></pre></td></tr></table></figure><p>E o parâmetro <code>bin</code>, é para que possamos dizer ao NPM que, quando executarmos <code>calculatr</code> no terminal, o arquivo que será chamado é o <code>calculatr.js</code>.</p><p>Adicione também mais uma entrada em <code>scripts</code>, no seu <code>package.json</code>. Ele deve ficar assim:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">"scripts": &#123;</span><br><span class="line">  "test": "istanbul cover _mocha -- -R spec",</span><br><span class="line">  "watch": "istanbul cover _mocha -- -R spec --watch"</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure><p>Para que possamos executar nossos testes sem precisar nos preocupar em ficar executando o comando <code>npm test</code> toda hora. Só precisaremos executar <code>npm run watch</code> e <em>voilà</em>!</p><p>E agora nosso <code>package.json</code> está pronto!</p><h2 id="Sobre-Versoes"><a href="#Sobre-Versoes" class="headerlink" title="Sobre Versões"></a>Sobre Versões</h2><p>As versões para os módulos funcionam mais ou menos assim: o terceiro número se refere somente a ajustes, solução de bugs, mas sem adicionar novas funcionalidades. Quando temos um módulo com versão <code>0.0.x</code>, onde <code>x</code> você incrementa a cada alteração que você fizer no módulo, chamamos de versão <code>alpha</code>. O segundo número, é quando você tem uma versão de algo já funcional. Então, a versão <code>0.1.0</code> tem a primeira versão <code>beta</code>, ou seja, ainda em testes, mas com alguma funcionalidade pronta. O incremento do segundo número deve ser a cada nova funcionalidade. O terceiro número continua sendo para resolver bugs, ou pequenos problemas. Então, se você tiver uma versão <code>0.1.3</code>, significa que, na versão beta, que tem <code>1</code> funcionalidade que funciona (?), você já fez <code>3</code> correções de bugs, ou ajustes.</p><p>E o último número, é quando você tem uma versão estável do módulo, com o mínimo de funcionalidades que você considera ideal para que ele seja um módulo “completo”. Esse completo é muito relativo, mas, dando o exemplo do nosso módulo, quando ele estiver somando dois números, ele já estará estável, e poderemos usar a versão <code>1.0.0</code>.</p><p>Nem todos os módulos seguem essa ideia. Alguns tem sua própria forma de gerenciar suas versões, mas a base é mais ou menos essa.</p><h2 id="Criando-o-modulo"><a href="#Criando-o-modulo" class="headerlink" title="Criando o módulo"></a>Criando o módulo</h2><p>Agora, vamos começar a criar nosso módulo!</p><p>Como boa prática, vamos primeiro aos testes :D</p><p>Crie um diretório <code>test</code>, e, dentro dele, um arquivo chamado <code>test.calculatr.js</code>. Antes de começar, vamos instalar as dependências que usaremos. Já temos o <code>istanbul</code>e o <code>mocha</code>, como citado anteriormente. Se não os tiver instalados globalmente ainda, instale.</p><p>Após isso, vamos às dependências para os testes:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev should</span><br></pre></td></tr></table></figure><p>Instalamos com <a href="https://blog.da2k.com.br/2015/03/03/gerenciando-corretamente-dependencias-em-nodejs-save-ou-save-dev-1/">–save-dev</a>, pois queremos o <code>should</code> somente para desenvolvimento, ele não fará parte da aplicação.</p><p>E então vamos escrever nosso primeiro teste. No arquivo <code>test/test.calculatr.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> exec = <span class="built_in">require</span>( <span class="string">'child_process'</span> ).exec;</span><br><span class="line"><span class="keyword">var</span> pkg = <span class="built_in">require</span>( <span class="string">'../package.json'</span> );</span><br><span class="line"><span class="keyword">var</span> calculatr = <span class="string">'./calculatr.js'</span>;</span><br><span class="line"><span class="built_in">require</span>( <span class="string">'should'</span> );</span><br><span class="line"></span><br><span class="line">describe( <span class="string">'Calculatr'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  it( <span class="string">'Should return version of calculatr'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">    exec( calculatr + <span class="string">' --version'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> err, stdout, stderr </span>) </span>&#123;</span><br><span class="line">      <span class="keyword">if</span>( err ) <span class="keyword">throw</span> err;</span><br><span class="line">      stdout.replace( <span class="string">'\n'</span>, <span class="string">''</span> ).should.be.equal( pkg.version );</span><br><span class="line">      done();</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p><em>Opa! Tem bastante coisa nova ae!</em></p><p>Sim, vou explicar tudo :D</p><p>O <code>require( &#39;child_process&#39; ).exec</code> faz parte do <strong>NodeJS</strong>. Ele vai nos ajudar a executar comandos no terminal, permitindo-nos usar uma função de callback para fazer nosso teste quando o comando for executado :)</p><p>Na linha <code>4</code>, adicionamos o nosso <code>package.json</code>, e já veremos o porquê!</p><p>Na linha <code>5</code>, vamos simular o comando para executar o <code>calculatr</code>, pois ainda não temos o módulo instalado globalmente. Mas quando ele for instalado, usando <code>calculatr</code> irá chamar o arquivo <code>calculatr.js</code> :)</p><p>Adicionamos o <code>should</code> para fazer os testes.</p><p>No primeiro teste, vamos verificar se nossa CLI retorna a versão correta. Se usarmos o comando <code>calculatr --version</code>, deveria retornar a versão. Na linha <code>10</code> você pode ver o teste sendo feito, usando o <code>exec</code> para dar o comando.</p><p>O que ele faz é bem simples: como primeiro parâmetro da função, passamos o comando <code>calculatr + &#39; --version&#39;</code>. A função de callback nos retorna, como primeiro parâmetro, um erro (se houver), depois a saída no terminal (<code>stdout</code>), ou algum erro para a saída (<code>stderr</code>).</p><p>O que iremos usar para testar é a saída (<code>stdout</code>). Fazemos o teste com o comando da linha <code>12</code>. Testamos se a saída - que retorna sempre uma quebra de linha no final, por isso o <code>replace</code> - é igual à versão do nosso projeto. Pegamos a versão diretamente do <code>package.json</code>, pois ela será atualizada constantemente. Se colocarmos manualmente, teremos que lembrar de alterar a cada versão lançada, para não quebrar nosso teste.</p><p>Usamos a função <code>done()</code>, que já vimos no artigo sobre <a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">como criar um módulo Ajax com Promises</a>, que serve para dizer à função <code>it()</code>, que é o nosso teste, que nossa asserção já foi feita, e ele pode verificar se passou ou não.</p><p>Obviamente, nosso teste quebra, pois ainda não temos nada no arquivo principal :)</p><p>Ainda antes de criar nosso módulo, você percebeu que no nosso teste não executamos o comando <code>node ./calculatr.js --version</code>, e sim <code>./calculatr.js --version</code>, sem o <code>node</code>?</p><p>Como essa é uma ferramenta de <strong>CLI</strong>, ela precisa ser executada sem o comando <code>node</code>, mas para isso, ela precisa de permissão de execução. Para dar essa permissão, execute no seu terminal, na raiz do projeto:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod +x calculatr.js</span><br></pre></td></tr></table></figure><p>Isso fará com que seja possível executar esse arquivo diretamente com o comando <code>./calculatr</code>! Mas ainda tem outro segredo que só vou contar quando escrevermos nosso módulo :P</p><p>Vamos fazê-lo agora! No arquivo <code>calculatr.js</code>, adicione:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env node</span></span><br><span class="line"><span class="string">'use strict'</span>;</span><br><span class="line"></span><br><span class="line">var program = require( <span class="string">'commander'</span> );</span><br><span class="line">var pkg = require( <span class="string">'./package.json'</span> );</span><br><span class="line"></span><br><span class="line">program.version( pkg.version );</span><br><span class="line">program.parse( process.argv );</span><br></pre></td></tr></table></figure><p>A primeira linha é essencial para nossa <strong>CLI</strong>, pois é ela que faz a mágica para que nosso módulo funcione sem precisar escrever em <em>shell script</em>: dizemos que, ao chamar esse arquivo - executando <code>./calculatr</code> no terminal - , o programa que irá executá-lo será o <code>node</code>!</p><p>Então, por baixo dos panos, ao executarmos <code>./calculatr</code>, na verdade, o comando executado será <code>node ./calculatr</code> ;)</p><p><em>Safadeeeenho! Mas pera, tem um módulo novo ali! O que é esse <strong>commander</strong>?</em></p><p>O <code>commander</code> nos ajuda a montar uma interface para usarmos na linha de comando. Você deve instalá-lo com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save commander</span><br></pre></td></tr></table></figure><p>Agora usamos o <code>--save</code>, pois esse módulo será uma dependência do nosso projeto. Toda vez que o baixarmos, também será baixado o <code>commander</code> :)</p><p>Na linha <code>7</code>, passamos para o <code>commander</code> a versão do nosso projeto. Pegamos direto do <code>package.json</code>, como fizemos no arquivo de teste. E na linha <code>8</code>, fazemos o parse com os argumentos que forem passados no terminal. O <code>process.argv</code> recebe uma coleção com os argumentos passados. Ao fazer o parse, podemos executar o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./calculatr.js --version</span><br></pre></td></tr></table></figure><p>Que retornará a versão da nossa ferramenta.</p><p>Agora, salvando o arquivo e olhando para o nosso teste, ele passou!! \o/</p><h2 id="Primeiro-metodo-soma-sum"><a href="#Primeiro-metodo-soma-sum" class="headerlink" title="Primeiro método: soma (sum)"></a>Primeiro método: soma (<code>sum</code>)</h2><p>Vamos fazer o primeiro método da nossa calculadora: a soma. Vamos receber, inicialmente, dois valores e somá-los.</p><p>E vamos usar o comando abaixo para efetuar a soma:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">calculatr sum 1 2</span><br></pre></td></tr></table></figure><p>Que deverá imprimir o resultado <code>3</code>. Vamos fazer o teste? No arquivo <code>test/test.calculatr.js</code>, adicine mais um teste:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Command "calculatr sum 1 2" Should return 3'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">  exec( calculatr + <span class="string">' sum 1 2'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> err, stdout, stderr </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( err ) <span class="keyword">throw</span> err;</span><br><span class="line">    <span class="built_in">Number</span>( stdout ).should.be.equal( <span class="number">3</span> );</span><br><span class="line">    done();</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>O formato desse teste é bem parecido com o anterior. Só mudaremos o comando, que agora é <code>calculatr + &#39; sum 1 2 &#39;</code>, que deveria retornar <code>3</code>. O retorno da CLI é sempre uma string, então precisamos converter para número antes de fazer o teste, por isso usamos o objeto <code>Number</code> aqui, e então verificamos se o resultado é <code>3</code>.</p><p>E adivinha: o teste NÃO PASSA! A-ha! ¬¬</p><p>Agora vamos fazer a implementação do código. Vamos modificar um pouco o arquivo <code>calculatr.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">program.version( pkg.version );</span><br><span class="line"></span><br><span class="line">program</span><br><span class="line">  .command( <span class="string">'sum &lt;number1&gt; &lt;number2&gt;'</span> )</span><br><span class="line">    .description( <span class="string">'Sum two numbers'</span> )</span><br><span class="line">    .action(<span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params"> number1, number2 </span>) </span>&#123;</span><br><span class="line">      <span class="built_in">console</span>.log( <span class="built_in">Number</span>( number1 ) + <span class="built_in">Number</span>( number2 ) );</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">program.parse( process.argv );</span><br></pre></td></tr></table></figure><p>Temos três métodos novos do <code>commander</code>: <code>command</code>, <code>description</code> e <code>action</code>. Nós poderíamos ter encadeado todos os métodos, ficando algo como:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">program</span><br><span class="line">  .version( pkg.version );</span><br><span class="line">  .command( <span class="string">'sum &lt;number1&gt; &lt;number2&gt;'</span> )</span><br><span class="line">  .description( <span class="string">'Sum two numbers'</span> )</span><br><span class="line">  .action(<span class="function"><span class="keyword">function</span> <span class="title">sum</span>(<span class="params"> number1, number2 </span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log( <span class="built_in">Number</span>( number1 ) + <span class="built_in">Number</span>( number2 ) );</span><br><span class="line">  &#125;)</span><br><span class="line">  .parse( process.argv );</span><br></pre></td></tr></table></figure><p>Se você achar que assim fica mais legível, fique à vontade :)</p><p>Separei pois acho que fica melhor deixar os comandos separados, já que poderemos adicionar mais funcionalidades à nossa ferramenta xD</p><p>O <code>command</code> recebe como parâmetro uma string, com o comando, e os argumentos que ele suporta. Quando você usa o parâmetro envolto por <code>&lt;</code> e <code>&gt;</code>, quer dizer que o parâmetro é obrigatório. Para parâmetros opcionais, use <code>[</code> e <code>]</code>.</p><p>Depois, o <code>description</code> é uma descrição sobre o comando. Essa descrição é útil quando você executa no terminal <code>calculatr --help</code>, onde será mostrado o <code>help</code> da sua ferramenta. O <code>commander</code> já deixa toda a interface de retorno do <code>help</code> bonitinha, no padrão da maioria dos <strong>CLIs</strong> em sistemas *nix :D</p><p>E a <code>action</code> é a ação para quando o comando for executado no terminal. Essa ação fica em uma função de callback, que recebe como parâmetro os argumentos passados no terminal. O primeiro é o primeiro número, o segundo, o próximo número.</p><p>No retorno, executamos um <code>console.log()</code>, para mostrar na saída do terminal, convertendo os dois parâmetros para número com <code>Number()</code> e retornando a soma dos mesmos.</p><p>E nosso teste passou \o/</p><p>O <code>commander</code> tem vários outros métodos legais. Para saber mais sobre ele, o TJ escreveu um post bem completo, que você pode ler <a href="http://tjholowaychuk.tumblr.com/post/9103188408/commander-js-nodejs-command-line-interfaces-made" target="_blank" rel="noopener">aqui</a>.</p><p><em>E agora, qual o próximo passo?</em></p><p>O próximo passo é subir nossa ferramenta no <a href="https://www.npmjs.com/" target="_blank" rel="noopener">https://www.npmjs.com/</a>!</p><h2 id="Subindo-o-modulo-no-NPMJS"><a href="#Subindo-o-modulo-no-NPMJS" class="headerlink" title="Subindo o módulo no NPMJS"></a>Subindo o módulo no NPMJS</h2><p>Para subir o módulo é bastante simples: você só precisa executar o comando:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm publish</span><br></pre></td></tr></table></figure><p>Mas antes de fazer isso, você precisa ter um cadastro no site do NPM, e configurar sua máquina para poder publicar seus módulos. Vamos ver como fazer isso!</p><p>O cadastro é simples: entre em <a href="https://www.npmjs.com/" target="_blank" rel="noopener">https://www.npmjs.com/</a>, e cadastre-se, como em qualquer outro site xD</p><p>Você ainda pode se cadastrar via terminal, com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm adduser</span><br></pre></td></tr></table></figure><p>Será pedido um nome de usuário, uma senha e um e-mail (que ficará público).</p><p>Se você já tinha cadastro no site, só precisa então logar no seu ambiente, com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm login</span><br></pre></td></tr></table></figure><p>Após isso, você precisa verificar se os seus dados estão corretamente configurados. Use o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config ls</span><br></pre></td></tr></table></figure><p>Isso irá listar os seus dados. Confira se tudo está correto.</p><p>Mas temos alguns arquivos que não queremos enviar para o NPMJS, como o diretório <code>test</code>, o <code>node_modules</code>, o diretório <code>coverage</code>, criado pelo <code>istanbul</code>.</p><p>Para isso, podemos criar um arquivo <code>.npmignore</code> na raiz do nosso projeto, e adicionar esses diretórios, como faríamos no <code>.gitignore</code>.</p><p>Feito isso, só executar o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm publish</span><br></pre></td></tr></table></figure><p>E aguardar! Quando o comando terminar de rodar, acesse o <a href="https://www.npmjs.com/package/nome-do-seu-pacote" target="_blank" rel="noopener">https://www.npmjs.com/package/nome-do-seu-pacote</a> e veja se o seu <strong>CLI</strong> está lá! Pronto, agora você tem uma ferramenta de <strong>CLI</strong> que funciona e está publicada no NPMJS!</p><p>Vamos testar se ela funciona? Instale-a globalmente, com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[sudo] npm i -g calculatr</span><br></pre></td></tr></table></figure><p>Coloquei o <code>sudo</code>, pois provavelmente você irá precisar dele. Tente primeiro instalar sem o <code>sudo</code>. Se não der certo, então use ele.</p><p>Agora com nosso módulo instalado, vamos executá-lo para testar, com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">calculatr sum 3 4</span><br></pre></td></tr></table></figure><p>E o resultado é: <code>7</code>!</p><p>Agora tudo pronto :D</p><p>Para ver o código completo desse projeto, você pode acessá-lo no <a href="https://github.com/fdaciuk/calculatr" target="_blank" rel="noopener">Github</a> ou no <a href="https://www.npmjs.com/package/calculatr" target="_blank" rel="noopener">NPMJS</a>.</p><p>Até a próxima! Dúvidas? Comente :D</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/nodejs-cli.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ferramentas de linha de comando ajudam quando você precisa executar tarefas mais rapidamente. Que tal aprender a criar você mesmo a sua? E em &lt;strong&gt;NodeJS&lt;/strong&gt;! E ainda disponibilizar no &lt;strong&gt;NPMJS&lt;/strong&gt;! Ficou curioso? Vem que eu te mostro como faz ;)&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="nodejs" scheme="https://blog.da2k.com.br/tags/nodejs/"/>
    
      <category term="cli" scheme="https://blog.da2k.com.br/tags/cli/"/>
    
  </entry>
  
  <entry>
    <title>Javascript - Criando um módulo Ajax com Promises - Parte 4</title>
    <link href="https://blog.da2k.com.br/2015/03/14/javascript-criando-um-modulo-ajax-com-promises-parte-4/"/>
    <id>https://blog.da2k.com.br/2015/03/14/javascript-criando-um-modulo-ajax-com-promises-parte-4/</id>
    <published>2015-03-14T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.862Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises4.png" alt=""></p><p>Após uma série de 4 posts (<a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">aqui</a>, <a href="https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/">aqui</a>, <a href="https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/">aqui</a> e <a href="https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/">aqui</a>), vamos começar a ver nosso módulo finalmente funcionando! Vem comigo :D</p><a id="more"></a><p>Vamos testar as funcionalidades do nosso módulo. Começaremos sempre pelo mais simples: o método <code>get</code>.<br>Ao requisitar uma URL da nossa API, via GET, esse método deve retornar um objeto.</p><p>Vamos ver então como ficaria o teste. Nosso arquivo de testes tem um bloco <code>describe</code> que está testando a interface do nosso módulo. Vamos criar então outro bloco <code>describe</code>, para testar a resposta de cada método, referente aos verbos HTTP, separadamente. Adicione ao arquivo <code>tests/test.ajax.js</code>, logo após o primeiro bloco <code>describe</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">describe( <span class="string">'Test `get` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  it( <span class="string">'Should return an object'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">    ajax.get( <span class="string">'http://localhost:3000/api/users'</span> ).done(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">      response.should.be.an( <span class="string">'object'</span> );</span><br><span class="line">      done();</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Temos várias coisas acontecendo aqui, vamos por partes:</p><p>Primeiro criamos nosso novo bloco de testes, na linha <code>1</code>, onde testaremos o método <code>get</code> do nosso módulo. Criamos o primeiro teste, na linha <code>2</code>, onde este deveria retornar, como resposta da requisição bem sucedida, um objeto.</p><p>Para testar se realmente funciona, precisamos fazer a asserção com a resposta da requisição. Então instanciamos o nosso módulo <code>Ajax</code>, na linha <code>3</code>, e logo após, na linha <code>4</code>, fazemos a requisição para uma URL utilizando o método <code>get</code>. Sabemos que esse método retorna outros dois métodos <code>done</code> e <code>error</code> - usados como <strong>Promises</strong> - que já testamos acima, garantindo que esses métodos existem.</p><p>Então passamos para o método <code>done</code> uma função de callback, que será chamada assim que nossa requisição retornar com sucesso. Essa função de callback recebe um parâmetro <code>response</code>, com os dados da nossa requisição.</p><p>Enfim, na linha <code>5</code>, fazemos a asserção, para verificar se o retorno é realmente um objeto. Se você não entendeu como esses métodos encadeados funcionam, formando uma frase, sugiro consultar a <a href="http://chaijs.com/api/bdd/" target="_blank" rel="noopener">documentação do <strong>Chai</strong></a>.</p><p><em>Mas o que é essa função <code>done()</code>, sendo invocada na linha <code>6</code>?</em></p><p>Quando precisamos testar métodos assíncronos, ou seja, quando não sabemos exatamente o momento da resposta, pois dependemos do retorno de um <em>callback</em>, o <strong>Mocha</strong> nos dá uma função que passamos como parâmetro na função <code>it()</code>, que pode ser invocada logo após nossa asserção, para dizer ao <strong>Mocha</strong> quando ele deve realmente verificar se nosso teste passa.</p><p>Como as requisições do nosso módulo serão sempre assíncronas (ainda iremos definir isso), precisamos usar a função <code>done()</code> para que o teste não execute antes que resposta da requisição esteja realmente pronta.</p><p>Se abrirmos a nossa <code>index.html</code>, que contém os testes, veremos que nosso teste NÃO PASSA. Era o que esperávamos, visto que não implementamos nada ainda!</p><p>Mas agora sabemos exatamente o que precisa ser feito: criaremos o processo que faz a requisição e responde ao método <code>done()</code> do nosso módulo :D</p><h2 id="Primeiro-problema-CORS"><a href="#Primeiro-problema-CORS" class="headerlink" title="Primeiro problema: CORS"></a>Primeiro problema: CORS</h2><p>Ao acessar a <code>index.html</code>, onde tem os testes, podemos ver no <em>console</em> do nosso navegador que temos um problema com <strong>CORS</strong>. Vamos resolver isso de forma prática, mas que não deve ser feita para toda aplicação: adicionaremos um <em>header</em> na nossa API, que permite que requisições de domínios diferentes consumam essa API. Vamos liberar para todos os domínios, mas fica o alerta: quando você criar uma API Rest, libere somente requisições para domínios específicos, ou então use um <em>acess token</em> para validar as requisições. Mas foi só um alerta, isso é assunto para um post somente sobre APIs Rest.</p><p>Voltando ao que interessa: vamos então adicionar o <em>header</em> à nossa API. No arquivo <code>api/app.js</code>, adicione logo após o objeto <code>users</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function"><span class="keyword">function</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">  res.setHeader( <span class="string">'Access-Control-Allow-Origin'</span>, <span class="string">'*'</span> );</span><br><span class="line">  next();</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Isso irá garantir que, antes de toda requisição, o <em>header</em> <code>Access-Control-Allow-Origin</code> seja passado, liberando acesso de qualquer domínio à nossa API :)</p><p>Agora vamos ao nosso módulo. Em <code>src/ajax.js</code>, vamos mudar um pouco nosso método <code>get</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"> url </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">  xhr.open( <span class="string">'GET'</span>, url, <span class="literal">true</span> );</span><br><span class="line">  xhr.addEventListener( <span class="string">'readystatechange'</span>, $private.handleReadyStateChange, <span class="literal">false</span> );</span><br><span class="line">  xhr.send();</span><br><span class="line">  <span class="keyword">return</span> $private.promises();</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Quando falamos em <strong>TDD</strong>, e desenvolver usando <em>baby steps</em>, sabemos que devemos escrever o mínimo de código possível para que nosso teste passe, e então ir refatorando até que o código fique aceitável. Nesse caso, escrevemos código até demais, mas tem um bom motivo: não estamos <strong>criando</strong> o <strong>XMLHttpRequest</strong>. Ele já existe, e precisa de uma quantidade mínima de código para funcionar corretamente. E as linhas adicionadas acima é o que precisamos para que uma requisição seja feita corretamente.</p><p>Primeiro passamos para o método <code>get</code> o parâmetro <code>url</code>, pois é à partir dele que iremos requisitar os dados do servidor. Na linha <code>2</code>, instanciamos o objeto <code>XMLHttpRequest</code>, que será responsável por fazer a requisição. Na linha <code>3</code>, abrimos uma nova conexão, passando o verbo <code>GET</code> (já que estamos usando o método <code>get()</code> do nosso módulo), depois a URL, e o terceiro parâmetro diz se a requisição será assíncrona ou não. Vamos deixá-lo como <code>true</code>, pois teremos <em>callbacks</em> para nos orientar quando a requisição tiver um retorno.</p><p>Na linha <code>4</code>, atrelamos ao nosso objeto um evento chamado <code>readystatechange</code>, onde poderemos tratar todos os passos da requisição. Na linha <code>5</code>, invocamos o método <code>send()</code>, que irá enviar a requisição ao servidor, para que comece a brincadeira! :D</p><p>No final, retornamos nesse método as <strong>Promises</strong>, pois queremos utilizar os métodos <code>done()</code> e <code>error()</code>, dependendo da resposta da requisição.</p><p>Como você sabe, cada <em>listener</em> de evento recebe como segundo parâmetro uma função de <em>callback</em>, onde será feito o tratamento dos dados quando aquele evento for disparado. Vamos ver como ficará o método <code>$private.handleReadyStateChange()</code>, no nosso módulo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$private.handleReadyStateChange = <span class="function"><span class="keyword">function</span> <span class="title">handleReadyStateChange</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log( <span class="keyword">this</span>.readyState === <span class="number">4</span> &amp;&amp; <span class="keyword">this</span>.status === <span class="number">200</span> &amp;&amp; <span class="built_in">JSON</span>.parse( <span class="keyword">this</span>.responseText ) );</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Antes de qualquer coisa, vamos verificar se os dados são retornados corretamente. Para isso, o objeto <code>XMLHttpRequest</code> tem uma propriedade somente leitura chamada <code>readyState</code> que, quando está em <code>4</code>, significa que a requisição está completa. A propriedade <code>status</code> retorna o <em>status HTTP</em> da requisição. 200 significa _OK_, ou seja, os dados foram retornados corretamente.</p><p>Em <code>responseText</code>, recebemos uma <em>DOMString</em>, com o resultado da requisição. Como estamos retornando um JSON do servidor, usamos o método <code>JSON.parse()</code> para <em>parsear</em> a string, transformando-a em um objeto do Javascript.</p><p>A resposta que temos é essa:</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/ajax-request.png" alt=""></p><p>Antes de retornar o objeto, podemos ver dois <em>requests</em> acusando <code>404</code>. Analisando o erro, vemos que é por causa do <em>assert</em> que testa a interface do método <code>get</code>, se ele retorna os métodos <code>done</code> e <code>error</code>. O erro acontece porque não estamos passando uma URL para o método, e o <em>XMLHttpRequest</em> tenta requisitar uma URL que não existe. Precisamos ajustar isso. Temos dois caminhos: ou simplesmente passamos uma string vazia na chamada <code>get()</code> do nosso objeto, ou validamos dentro do nosso módulo que, se não for passada nenhuma URL, ele passa uma string vazia, considerando a URL atual.</p><p>Vamos alterar nosso módulo, para manter retrocompatibilidade. Imagine que outras pessoas já estão usando esse módulo, então não podemos fazer com que a atualização do mesmo quebre os projetos que usam versões mais antigas. No método <code>get()</code> do nosso módulo, em <code>src/ajax.js</code>, vamos adicionar:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xhr.open( <span class="string">'GET'</span>, url || <span class="string">''</span>, <span class="literal">true</span> );</span><br></pre></td></tr></table></figure><p>Dessa forma, se não for passada URL alguma, consideramos a URL atual, passando uma string vazia, e não precisamos mudar as implementações anteriores :)</p><p>Hora de fazer nossas promises funcionarem! Nosso método <code>get()</code> retorna os métodos <code>done()</code> e <code>error()</code>, mas não é no exato momento do retorno desse método que as informações estarão disponíveis, mas sim no retorno do <em>callback</em> do evento <code>readystatechange</code>. Então nós precisaremos de um objeto auxiliar, que será usado para fazer com que as nossas <strong>Promises</strong> conversem com o retorno da requisição.</p><p>Parece complicado? Vamos ver na prática como fazer isso! Primeiro, no nosso módulo, criaremos o objeto auxiliar. No início do módulo, em <code>src/ajax.js</code>, logo após as declarações dos objetos <code>$public</code> e <code>$private</code>, adicione:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$private.methods = &#123;</span><br><span class="line">  done: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;&#125;,</span><br><span class="line">  error: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Esse objeto conterá os métodos que nos auxiliarão a criar nossas <strong>Promises</strong>.</p><p>Agora, na função de callback do evento <code>readystatechange</code>, vamos adicionar os métodos <code>done()</code> e <code>error()</code> ao <code>$private.methods</code>, e invocá-los, passando a resposta da requisição para eles. Mudando o método <code>$private.handleReadyStateChange()</code>, vamos agora ter o seguinte:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$private.handleReadyStateChange = <span class="function"><span class="keyword">function</span> <span class="title">handleReadyStateChange</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> xhr = <span class="keyword">this</span>;</span><br><span class="line">  <span class="keyword">var</span> DONE = <span class="number">4</span>;</span><br><span class="line">  <span class="keyword">if</span>( xhr.readyState === DONE ) &#123;</span><br><span class="line">    <span class="keyword">if</span>( xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span> ) &#123;</span><br><span class="line">      <span class="keyword">return</span> $private.methods.done.call( $private.methods, <span class="built_in">JSON</span>.parse( xhr.responseText ) );</span><br><span class="line">    &#125;</span><br><span class="line">    $private.methods.error.call( $private.methods, <span class="built_in">JSON</span>.parse( xhr.responseText ) );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Só vamos retornar algo quando a requisição estiver completa, por isso fazemos a verificação do <code>xhr.readyState</code> na linha <code>4</code>. Na linha <code>5</code>, verificamos se o status HTTP da requisição está OK, ou seja, se for um status entre <code>200</code> e <code>300</code>, a requisição retornou com sucesso.</p><p>Na linha <code>6</code> é onde acontece a primeira parte da magia das <strong>Promises</strong>: usamos o objeto <code>$private.methods</code>, invocando o método <code>done()</code> com o <code>call()</code>, e setamos o próprio objeto para ser o <code>this</code> dentro do método <code>done()</code>. Passamos também como parâmetro o JSON de resposta da requisição, já parseado como objeto Javascript.</p><p>Mas tem um porém: esse método <code>$private.methods.done( response )</code>, que recebe esse parâmetro <code>response</code>, deve ser a função de <em>callback</em> que passaremos como parâmetro do método <code>done()</code> da <strong>Promise</strong>.</p><p>Para que isso seja possível, vamos mexer um pouco no método <code>$private.promises()</code> do nosso módulo, fazendo com que, quando os métodos <code>done()</code> e <code>error()</code> do módulo Ajax, quando forem chamados, recebam essa função como callback:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">$private.promises = <span class="function"><span class="keyword">function</span> <span class="title">promises</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    done: <span class="function"><span class="keyword">function</span> <span class="title">done</span>(<span class="params"> callback </span>) </span>&#123;</span><br><span class="line">      $private.methods.done = callback;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    error: <span class="function"><span class="keyword">function</span> <span class="title">error</span>(<span class="params"> callback </span>) </span>&#123;</span><br><span class="line">      $private.methods.error = callback;</span><br><span class="line">      <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Complicou? Pois é, eu disse que seria uma aventura :D</p><p>Vou explicar o que acontece: quando invocamos o método <code>get()</code> do nosso módulo, através de:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">ajax.get( <span class="string">'http://localhost:3000/api/users'</span> );</span><br></pre></td></tr></table></figure><p>Nós temos disponíveis outros dois métodos: <code>done()</code> e <code>error()</code>, que são chamados através do <code>return $private.promises()</code> dentro do método <code>get()</code> no nosso módulo.</p><p>No método <code>$private.promises()</code> - atualizado acima - nós retornamos esses dois métodos <code>done()</code> e <code>error()</code>, que recebem como parâmetro uma função de callback.</p><p>Então, nós atribuímos ao objeto <code>$private.methods</code> o callback passado como parâmetro.</p><p>Lá na função de callback do evento <code>readystatechange</code>, você viu que invocamos o <code>$private.methods.done</code> e o <code>$private.methods.error</code> com o <code>call</code>, passando o <code>xhr.responseText</code> como parâmetro desses métodos.</p><p>É aproveitando-se da natureza funcional do Javascript que conseguimos fazer as <strong>Promises</strong> conversarem com o retorno dos métodos no momento certo, retornando a interface que temos agora!</p><p>E se você perceber, ainda no método <code>$private.promises()</code>, dentro dos métodos <code>done()</code> e <code>error()</code>, nós retornamos o <code>this</code>, que é o próprio objeto retornado nesse método, para que possamos encadear as respostas, exatamente como vimos no <a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">primeiro artigo dessa série</a>, mas com jQuery :D</p><p>Por isso, nós podemos utilizar nosso módulo dessa forma:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">ajax.get( <span class="string">'http://localhost:3000/api/users'</span> )</span><br><span class="line">  .done(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">    <span class="comment">// =&gt; sucesso</span></span><br><span class="line">  &#125;)</span><br><span class="line">  .error(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="comment">// =&gt; erro</span></span><br><span class="line">  &#125;);</span><br></pre></td></tr></table></figure><p>Vamos executar nosso teste para ver se agora passa:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Error: Uncaught SyntaxError: Unexpected token &lt; (http://localhost/00-opensource/ajax/:1)</span><br><span class="line">    at process.on.global.onerror (http://localhost/00-opensource/ajax/public/mocha.js:6366:10)</span><br></pre></td></tr></table></figure><p>Opa! Alguma coisa deu errado! O que aconteceu?</p><p>Vamos tentar debugar, para ver se a resposta está vindo corretamente. Em nosso teste, em <code>tests/test.ajax.js</code>, vamos adicionar um <code>console.log( response )</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should return an object'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  ajax.get( <span class="string">'http://localhost:3000/api/users'</span> ).done(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log( response );</span><br><span class="line">    response.should.be.an( <span class="string">'object'</span> );</span><br><span class="line">    done();</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>E vemos que, como esperado, o nosso objeto é retornado com sucesso! Mas está dando um erro de sintaxe no teste!</p><p>O que acontece é que, em algum momento, o resultado que é retornado por nossa API como JSON, é convertido para <em>string</em>, com <code>toString()</code> (não sei porque o <strong>Mocha</strong> faz isso), e depois, quando tentamos fazer o parse com <code>JSON.parse</code>, acontece o erro de sintaxe.</p><p>Como o formato da resposta pode variar, temos que garantir que nosso módulo traga a resposta corretamente. Então vamos fazer uma pequena modificação no método <code>$private.handleReadyStateChange</code> do nosso método, em <code>src/ajax.js</code>, para ficar assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>( xhr.readyState === DONE ) &#123;</span><br><span class="line">  <span class="keyword">if</span>( xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span> ) &#123;</span><br><span class="line">    <span class="keyword">return</span> $private.methods.done( $private.parseResponse( xhr.responseText ) );</span><br><span class="line">  &#125;</span><br><span class="line">  $private.methods.error( $private.parseResponse( xhr.responseText ) );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Somente vamos chamar um método <code>$private.parseResponse</code>, passando como parâmetro a resposta da requisição. Nesse método, vamos tratar o parse do JSON:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$private.parseResponse = <span class="function"><span class="keyword">function</span> <span class="title">parseResponse</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> result;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    result = <span class="built_in">JSON</span>.parse( response );</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">catch</span>( e ) &#123;</span><br><span class="line">    result = response;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> result;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>E pronto! Simplesmente colocamos o retorno em um bloco <code>try/catch</code>. Se der erro ao tentar parsear, retornamos somente a resposta, que já deve estar em JSON :D</p><p>Agora o nosso teste passou! Ufa!</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/get-method-return-true.png" alt=""></p><p>Agora você está vendo como realmente as <strong>Promises</strong> funcionam. Não precisamos de nenhuma <em>library</em> ou <em>framework</em> para fazê-las funcionar. Claro que não é um trabalho tão simples, mas conhecendo um pouco de programação funcional, nós conseguimos fazer uma funcionalidade onde antes precisaríamos carregar um lib inteira como a <code>Q</code> ou <code>async</code> só para fazer isso!</p><p>Mas ainda não acabou: já temos nosso módulo funcional, mas ainda temos testes a fazer! Precisamos testar agora o próximo método: o <code>post</code>.<br>Mas como esse artigo já está grande demais, o método <code>post</code> ficará para o próximo artigo! Não perca :D</p><p>Ficou com dúvida de algo? Não fique com vergonha! Comente :D</p><p>Até o próximo! o/</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Após uma série de 4 posts (&lt;a href=&quot;https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/&quot;&gt;aqui&lt;/a&gt;, &lt;a href=&quot;https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/&quot;&gt;aqui&lt;/a&gt;, &lt;a href=&quot;https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/&quot;&gt;aqui&lt;/a&gt; e &lt;a href=&quot;https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/&quot;&gt;aqui&lt;/a&gt;), vamos começar a ver nosso módulo finalmente funcionando! Vem comigo :D&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="ajax" scheme="https://blog.da2k.com.br/tags/ajax/"/>
    
  </entry>
  
  <entry>
    <title>Javascript - Criando um módulo Ajax com Promises - Parte 3</title>
    <link href="https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/"/>
    <id>https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/</id>
    <published>2015-03-11T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.862Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises3.png" alt=""></p><p>Já vimos o quanto <em>callback hell</em> é ruim, e como as <strong>Promises</strong> resolvem o problema. Agora estamos criando nosso próprio módulo Ajax, que retorna <strong>Promises</strong> <code>done</code> e <code>error</code> para que saibamos exatamente o momento em que a requisição retornou algum resultado.</p><a id="more"></a><p>Como vimos no <a href="https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/">artigo anterior</a>, após todos os nossos testes estarem passando, é hora de verificarmos se nosso código precisa de um <em>refactory</em>. Como tínhamos algumas duplicidades, criamos um novo método e centralizamos o código para remover a duplicidade.</p><p>Mas código limpo não vale apenas para o nosso código final, e sim também para os <strong>testes</strong>! Isso mesmo! Se você der uma olhada no nosso arquivo de testes <code>tests/test.ajax.js</code>, vai perceber que, em todos os testes, estamos instanciando o objeto <code>Ajax</code>.</p><p>Ainda não precisamos de instâncias diferentes, então podemos centralizar tudo em uma única chamada, no início da função <code>describe()</code>, que centraliza os testes de interface, e remover as chamadas dentro de cada teste (funções <code>it()</code>).</p><p>Nosso arquivo de testes, <code>tests/test.ajax.js</code>, refatorado, agora está assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">describe( <span class="string">'Test module interface'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should have `get` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    ajax.should.have.property( <span class="string">'get'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should have `post` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    ajax.should.have.property( <span class="string">'post'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should have `put` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    ajax.should.have.property( <span class="string">'put'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should have `delete` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    ajax.should.have.property( <span class="string">'delete'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `get` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> getRequest = ajax.get();</span><br><span class="line">    getRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `get` method return `error` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> getRequest = ajax.get();</span><br><span class="line">    getRequest.should.have.property( <span class="string">'error'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `post` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> postRequest = ajax.post();</span><br><span class="line">    postRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `post` method return `error` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> postRequest = ajax.post();</span><br><span class="line">    postRequest.should.have.property( <span class="string">'error'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `put` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> putRequest = ajax.put();</span><br><span class="line">    putRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `put` method return `error` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> putRequest = ajax.put();</span><br><span class="line">    putRequest.should.have.property( <span class="string">'error'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `delete` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> deleteRequest = ajax.delete();</span><br><span class="line">    deleteRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  it( <span class="string">'Should `delete` method return `error` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> deleteRequest = ajax.delete();</span><br><span class="line">    deleteRequest.should.have.property( <span class="string">'error'</span> );</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Agora que temos nosso código refatorado, e nossos testes também refatorados, podemos dar continuidade ao módulo o/</p><p>Precisamos fazer nosso módulo funcionar de verdade. Como a funcionalidade dele depende de requisições <code>get</code>, <code>post</code>, <code>put</code> e <code>delete</code>, antes de escrever a funcionalidade, e até mesmo antes de testar, precisamos ter um ambiente básico de <em>backend</em> que responda à esses métodos.</p><p>Vamos então criar uma API Rest básica, com NodeJS, para que possamos testar a resposta à esses 4 métodos.</p><h2 id="Criando-a-API-Rest"><a href="#Criando-a-API-Rest" class="headerlink" title="Criando a API Rest"></a>Criando a API Rest</h2><p>Quando falamos sobre como utilizar o <a href="https://blog.da2k.com.br/2015/03/02/gulp-criando-redirecionamentos-com-gulp-connect-connect-modrewrite/"><strong>Gulp</strong> com o <strong>connect</strong> e o <strong>modrewrite</strong></a> foi mostrado um exemplo básico de API Rest. Vamos usar a mesma ideia, só incrementando com os métodos <code>put</code> e <code>delete</code>.</p><p>Crie um diretório <code>api</code> na raiz do projeto, e um arquivo chamado <code>app.js</code> dentro desse diretório. E então, vamos para o código da nossa API:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> connect = <span class="built_in">require</span>( <span class="string">'connect'</span> );</span><br><span class="line"><span class="keyword">var</span> connectRoute = <span class="built_in">require</span>( <span class="string">'connect-route'</span> );</span><br><span class="line"><span class="keyword">var</span> app = connect();</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> users = &#123;</span><br><span class="line">  joao: &#123; <span class="attr">name</span>: <span class="string">'João da Silva'</span>, <span class="attr">age</span>: <span class="number">30</span> &#125;,</span><br><span class="line">  maria: &#123; <span class="attr">name</span>: <span class="string">'Maria Firmina'</span>, <span class="attr">age</span>: <span class="number">26</span> &#125;,</span><br><span class="line">  paulo: &#123; <span class="attr">name</span>: <span class="string">'Paulo Torres'</span>, <span class="attr">age</span>: <span class="number">25</span> &#125;</span><br><span class="line">&#125;;</span><br><span class="line">  </span><br><span class="line">app.use( connectRoute( <span class="function"><span class="keyword">function</span>(<span class="params"> router </span>) </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">postRequest</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">    res.setHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/json'</span> );</span><br><span class="line">    res.end( <span class="built_in">JSON</span>.stringify( users[ req.params.slug ] ) );</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  router.get( <span class="string">'/api/users'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">    res.setHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/json'</span> );</span><br><span class="line">    res.end( <span class="built_in">JSON</span>.stringify( users ) );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  router.post( <span class="string">'/api/user/:slug'</span>, postRequest );</span><br><span class="line">  router.put( <span class="string">'/api/user/:slug'</span>, postRequest );</span><br><span class="line">  router.delete( <span class="string">'/api/user/:slug'</span>, postRequest );</span><br><span class="line">&#125;));</span><br><span class="line">  </span><br><span class="line">app.listen( <span class="number">3000</span> );</span><br><span class="line">  </span><br><span class="line">exports = <span class="built_in">module</span>.exports = app;</span><br></pre></td></tr></table></figure><p>A única diferença para o código que fizemos no outro arquivo são os novos métodos e também exportamos a variável <code>app</code>, para que possamos importar em outro arquivo, e subir nosso servidor com o <strong>Gulp</strong>.</p><p>Agora, na raiz do projeto, você precisa instalar os módulos necessários:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev connect connect-route</span><br></pre></td></tr></table></figure><p>E já temos nossa API respondendo à todos os verbos que precisamos! :D</p><h2 id="Subindo-o-servidor"><a href="#Subindo-o-servidor" class="headerlink" title="Subindo o servidor"></a>Subindo o servidor</h2><p>Para subir o servidor, vamos adicionar a nossa API à <em>task</em> <code>default</code> do <strong>Gulp</strong>. No <code>gulpfile.js</code>, altere a <em>task</em> <code>default</code> para ficar assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">gulp.task( <span class="string">'default'</span>, [ <span class="string">'assets'</span> ], <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">require</span>( <span class="string">'./api/app'</span> );</span><br><span class="line">  gulp.watch([ allTestFiles, <span class="string">'src/ajax.js'</span> ], [ <span class="string">'test'</span> ]);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Lembra que exportamos o <code>app</code> na API, usando <code>exports = module.exports = app</code>? Esse comando vai servir para que possamos usar o <code>require</code> para adicionar o <code>app.js</code> onde quisermos! No nosso caso, ao executar a task <code>default</code> do <strong>Gulp</strong>, também subiremos nossa API, na porta 3000.</p><p>Agora, executando o comando <code>gulp</code> no terminal, você terá os testes rodando, o <em>coverage</em> e também a nossa API Rest, - que pode ser acessado via <code>http://localhost:3000</code> - para testar os métodos do nosso módulo de Ajax! :D</p><p>Para testar a API, você pode utilizar o <strong>Postman</strong>, por exemplo :)</p><p>Agora já temos tudo o que precisamos para ver nosso módulo funcionando! No próximo artigo vamos finalmente fechar com chave de ouro! :D</p><p>Se ficou alguma dúvida, comente!</p><p>Até lá! :D</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Já vimos o quanto &lt;em&gt;callback hell&lt;/em&gt; é ruim, e como as &lt;strong&gt;Promises&lt;/strong&gt; resolvem o problema. Agora estamos criando nosso próprio módulo Ajax, que retorna &lt;strong&gt;Promises&lt;/strong&gt; &lt;code&gt;done&lt;/code&gt; e &lt;code&gt;error&lt;/code&gt; para que saibamos exatamente o momento em que a requisição retornou algum resultado.&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="ajax" scheme="https://blog.da2k.com.br/tags/ajax/"/>
    
  </entry>
  
  <entry>
    <title>Javascript - Criando um módulo Ajax com Promises - Parte 2</title>
    <link href="https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/"/>
    <id>https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/</id>
    <published>2015-03-08T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.858Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises2.png" alt=""></p><p>E então, fez sua lição de casa proposta no <a href="https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/">post anterior</a>? xD<br>Vamos então dar continuidade no nosso módulo, para que possamos trabalhar com Ajax de forma organizada, e sem depender de módulos de terceiros o/</p><a id="more"></a><p>Nosso próximo passo é testar se nosso módulo tem os métodos <code>post</code>, <code>put</code> e <code>delete</code>.</p><p>No arquivo <code>tests/test.ajax.js</code>, vamos criar um novo teste, logo após o teste do <code>get</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should have `post` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  ajax.should.have.property( <span class="string">'post'</span> );</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Testamos agora pelo método <code>post</code>. É óbvio que ele não existe, mas é por isso que esse teste chama-se TDD, não? Primeiro testamos se algo existe, para que o teste falhe, e logo após, fazemos sua implementação, com o mínimo de código possível.</p><p>Vamos então adicionar no arquivo <code>src/ajax.js</code>, logo após o método <code>get</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br></pre></td></tr></table></figure><p>E o nosso teste passa! Agora ficou fácil, não? Vou deixar então pra você criar os métodos <code>put</code> e <code>delete</code> ;)</p><p>Lembrando que você pode acompanhar o desenvolvimento desse módulo <a href="https://github.com/fdaciuk/ajax" target="_blank" rel="noopener">aqui</a>.</p><p>Só um detalhe sobre o método <code>delete</code>: como <code>delete</code> é um operador válido em Javascript, você não pode utilizá-lo como nome de variável ou função, mas pode usá-lo como método ou propriedade de um objeto. Então, vamos nomear nossa função somente como <code>del</code>, no arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$public.delete = <span class="function"><span class="keyword">function</span> <span class="title">del</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br></pre></td></tr></table></figure><p>Assim não teremos problemas ;)</p><p><em>Certo, e qual é o próximo passo?</em></p><p>Ainda não testamos o retorno dos nossos métodos. Ainda dentro dos testes de interface do nosso módulo, precisamos garantir que eles retornem os métodos <code>done</code> e <code>error</code>. Esses métodos ainda não precisamo funcionar, só precisamos ter certeza que eles serão retornados, já que estamos falando de <strong>Promises</strong> :)</p><p>Criaremos um novo teste então, verificando se o nosso método <code>get</code> retorna esses dois outros métodos. No arquivo <code>tests/test.ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should `get` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  <span class="keyword">var</span> getRequest = ajax.get();</span><br><span class="line">  getRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Testamos primeiro pelo método <code>done</code>. Ele ainda não existe, logo nosso teste falha. Vamos então criá-lo:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    done: <span class="function"><span class="keyword">function</span> <span class="title">done</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><em>É só isso? Retornar um método <code>done</code> vazio?</em></p><p>Sim! Não é isso que o nosso teste pede: um método <code>done</code>? Então é isso que damos a ele :)</p><p>Precisamos sempre pensar simples, para dar somente o código necessário que o nosso teste precisa, e fazê-lo passar. A funcionalidade do método será feita depois, logo, ela será testada depois, então não precisamos nos preocupar com ela agora.</p><p>Dessa forma você mantém seus códigos com o mínimo de código possível, fazendo com que tudo fique tão limpo quanto possível :D</p><p>Agora precisamos testar o método <code>error</code>. No arquivo de testes <code>test/test.ajax.js</code>, vamos fazer a asserção para esse método:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should `get` method return `error` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  <span class="keyword">var</span> getRequest = ajax.get();</span><br><span class="line">  getRequest.should.have.property( <span class="string">'error'</span> );</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Então, escrevemos o código para que nosso teste passe. Em <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    done: <span class="function"><span class="keyword">function</span> <span class="title">done</span>(<span class="params"></span>) </span>&#123;&#125;,</span><br><span class="line">    error: <span class="function"><span class="keyword">function</span> <span class="title">error</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Adicionamos o método <code>error</code>, para que seja retornado por <code>get</code> e nosso teste volta a passar!</p><p><em>Mas e os outros métodos?</em></p><p>Então, todos os nossos métodos precisam retornar os mesmos métodos <code>done</code> e <code>error</code>. Vamos agora testar próximo método, <code>post</code>, para que ele também retorne as <strong>Promises</strong> <code>done</code> e <code>error</code>. Começamos por <code>done</code>. No arquivo <code>tests/test.ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">it( <span class="string">'Should `post` method return `done` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">  <span class="keyword">var</span> postRequest = ajax.post();</span><br><span class="line">  postRequest.should.have.property( <span class="string">'done'</span> );</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Nosso método <code>post</code> também deveria retornar <code>done</code> - assim diz o teste, que por sinal, falhou. Vamos então fazê-lo retornar o método <code>done</code>. No arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    done: <span class="function"><span class="keyword">function</span> <span class="title">done</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>E nosso teste volta a passar! Mas perceba uma coisa: o retorno do método <code>post</code> é exatamente igual - ou está se encaminhando para ser igual - ao retorno do método <code>get</code>. Como todos os nossos testes até aqui passaram, vamos parar de criar funcionalidades e aplicar o <span style="color: blue">BLUE</span>, fazendo um <em>refactory</em>. No arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Ajax</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> $public = &#123;&#125;;</span><br><span class="line">  <span class="keyword">var</span> $private = &#123;&#125;;</span><br><span class="line"></span><br><span class="line">  $public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> $private.promises();</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  $public.post = <span class="function"><span class="keyword">function</span> <span class="title">post</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> $private.promises();</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  $public.put = <span class="function"><span class="keyword">function</span> <span class="title">put</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line">  $public.delete = <span class="function"><span class="keyword">function</span> <span class="title">del</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line">  $private.promises = <span class="function"><span class="keyword">function</span> <span class="title">promises</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      done: <span class="function"><span class="keyword">function</span> <span class="title">done</span>(<span class="params"></span>) </span>&#123;&#125;,</span><br><span class="line">      error: <span class="function"><span class="keyword">function</span> <span class="title">error</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;;</span><br></pre></td></tr></table></figure><p>A função <code>Ajax</code> do nosso módulo agora ficou um pouco mais limpa: removemos a duplicidade do código, criando um método <code>$private.promises</code>, que retorna os métodos da <strong>Promise</strong> - <code>done</code> e <code>error</code>.</p><p>Deixamos o método <code>promises()</code> no objeto <code>$private</code>, pois não precisamos que ele seja acessado através da interface do nosso módulo. Ou seja, ninguém conseguirá chamar assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">ajax.promises();</span><br></pre></td></tr></table></figure><p>Isso irá retornar um erro dizendo que <code>undefined is not a function</code>, pois o método <code>promises()</code> não é público :D</p><p>Agora só precisamos criar os outros testes de <strong>Promises</strong> para os outros métodos <code>put</code> e <code>delete</code>, para manter tudo documentado.</p><p>Como você pode perceber, o resultado dos nossos testes, além de garantir que tudo está funcionando, acabam servindo como documentação do nosso código. Não precisamos usar comentários dentro do módulo para dizer o que cada coisa faz, já que os testes já o fazem por nós :D</p><p>Quando alguém ler o resultado dos testes, ele saberá exatamente quais são os métodos disponíveis para uso!</p><p>Já temos os testes para toda a nossa interface pronta, mas a continuação ficará para o <a href="https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/">próximo artigo</a>. Até lá!</p><p>Dúvidas até aqui? Comente :D</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/ajax-module-with-promises2.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;E então, fez sua lição de casa proposta no &lt;a href=&quot;https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/&quot;&gt;post anterior&lt;/a&gt;? xD&lt;br&gt;Vamos então dar continuidade no nosso módulo, para que possamos trabalhar com Ajax de forma organizada, e sem depender de módulos de terceiros o/&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="ajax" scheme="https://blog.da2k.com.br/tags/ajax/"/>
    
  </entry>
  
  <entry>
    <title>Javascript - Criando um módulo Ajax com Promises - Parte 1</title>
    <link href="https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/"/>
    <id>https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/</id>
    <published>2015-03-06T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.862Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/uploads/2015/03/ajax-module-with-promises.png" alt=""></p><p>No <a href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/">artigo anterior</a>, você viu como as <strong>Promises</strong> resolvem o problema de <em>callback hell</em>. Agora vamos ver na prática como criar nossas próprias <strong>Promises</strong>!</p><a id="more"></a><h2 id="O-que-iremos-fazer"><a href="#O-que-iremos-fazer" class="headerlink" title="O que iremos fazer?"></a>O que iremos fazer?</h2><p>Nosso desafio é criar um módulo para usar <strong>Ajax</strong>, sem qualquer <em>library</em> ou <em>framework</em>, e que possamos obter os resultados das requisições via <strong>Promises</strong>.</p><p>O nosso módulo será feito usando a técnica de <a href="https://blog.da2k.com.br/2015/01/06/pensando-tdd-com-javascript/">TDD</a>, ou seja, primeiro criamos um teste com o resultado esperado, e então partimos para o código em si :)</p><p>E o nosso primeiro passo é criar a estrutura do nosso projeto!</p><blockquote><p>Você pode acompanhar o andamento desse módulo através <a href="https://github.com/fdaciuk/ajax" target="_blank" rel="noopener">desse repositório no Github</a> :D</p></blockquote><h2 id="O-que-da-pra-fazer-com-Ajax"><a href="#O-que-da-pra-fazer-com-Ajax" class="headerlink" title="O que dá pra fazer com Ajax?"></a>O que dá pra fazer com Ajax?</h2><p>Acho que o exemplo mais comum é o <a href="https://www.facebook.com/photo.php?fbid=437375279637294&amp;set=pb.100000944779095.-2207520000.1425703771.&amp;type=3&amp;theater" target="_blank" rel="noopener">carrinho de compras com Ajax.</a></p><h2 id="Estrutura-do-projeto"><a href="#Estrutura-do-projeto" class="headerlink" title="Estrutura do projeto"></a>Estrutura do projeto</h2><p>Execute o comando abaixo no seu terminal, em um diretório separado para o projeto:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir src tests &amp;&amp; touch .editorconfig .jshintrc .gitignore gulpfile.js index.html src/ajax.js tests/test.ajax.js &amp;&amp; <span class="built_in">echo</span> <span class="string">"&#123;&#125;"</span> &gt; package.json</span><br></pre></td></tr></table></figure><p>Isso irá gerar a seguinte estrutura:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── .editorconfig</span><br><span class="line">├── .gitignore</span><br><span class="line">├── .jshintrc</span><br><span class="line">├── gulpfile.js</span><br><span class="line">├── package.json</span><br><span class="line">├── src</span><br><span class="line">│   └── ajax.js</span><br><span class="line">└── tests</span><br><span class="line">    └── ajaxTest.js</span><br></pre></td></tr></table></figure><p>Com nosso projeto criado, vamos montar nosso ambiente de testes :D</p><h2 id="Montando-o-ambiente-de-testes"><a href="#Montando-o-ambiente-de-testes" class="headerlink" title="Montando o ambiente de testes"></a>Montando o ambiente de testes</h2><p>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 <a href="https://blog.da2k.com.br/2015/01/06/pensando-tdd-com-javascript/">esse artigo</a> antes de continuar :D</p><p>Vamos instalar os módulos do <strong>Gulp</strong> necessários para que possamos fazer os testes no nosso módulo:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev gulp gulp-mocha gulp-istanbul gulp-load-plugins chai</span><br></pre></td></tr></table></figure><h2 id="Configuracoes-dos-arquivos"><a href="#Configuracoes-dos-arquivos" class="headerlink" title="Configurações dos arquivos"></a>Configurações dos arquivos</h2><p>Nosso arquivo <code>.jshintrc</code> ficará assim:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"curly"</span>   : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"eqeqeq"</span>  : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"immed"</span>   : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"latedef"</span> : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"newcap"</span>  : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"noarg"</span>   : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"sub"</span>     : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"undef"</span>   : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"boss"</span>    : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"eqnull"</span>  : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"node"</span>    : <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"globals"</span> : &#123;</span><br><span class="line">    <span class="attr">"document"</span> : <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">"window"</span>   : <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Já o <code>.editorconfig</code> terá a seguinte configuração:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">root</span> <span class="string">=</span> <span class="literal">true</span></span><br><span class="line">  </span><br><span class="line"><span class="string">[*]</span></span><br><span class="line"><span class="string">charset</span> <span class="string">=</span> <span class="string">utf-8</span></span><br><span class="line"><span class="string">end_of_line</span> <span class="string">=</span> <span class="string">lf</span></span><br><span class="line"><span class="string">insert_final_newline</span> <span class="string">=</span> <span class="literal">false</span></span><br><span class="line"><span class="string">indent_style</span> <span class="string">=</span> <span class="string">space</span></span><br><span class="line"><span class="string">indent_size</span> <span class="string">=</span> <span class="number">2</span></span><br><span class="line"><span class="string">trim_trailing_whitespace</span> <span class="string">=</span> <span class="literal">true</span></span><br><span class="line">  </span><br><span class="line"><span class="string">[*.md]</span></span><br><span class="line"><span class="string">trim_trailing_whitespace</span> <span class="string">=</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>E o <code>.gitignore</code>:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node_modules/</span><br></pre></td></tr></table></figure><p>E agora vamos configurar nosso <code>gulpfile.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>( <span class="string">'gulp'</span> );</span><br><span class="line"><span class="keyword">var</span> g = <span class="built_in">require</span>( <span class="string">'gulp-load-plugins'</span> )();</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> allTestFiles = <span class="string">'./tests/**/*.js'</span>;</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'assets'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  gulp.src([</span><br><span class="line">    <span class="string">'node_modules/gulp-mocha/node_modules/mocha/mocha.&#123;js,css&#125;'</span>,</span><br><span class="line">    <span class="string">'node_modules/chai/chai.js'</span></span><br><span class="line">  ])</span><br><span class="line">  .pipe( gulp.dest( <span class="string">'public'</span> ) );</span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'mocha'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  gulp.src([ allTestFiles ], &#123; <span class="attr">read</span> : <span class="literal">false</span> &#125;)</span><br><span class="line">  .pipe(</span><br><span class="line">    g.mocha(&#123; <span class="attr">reporter</span>: <span class="string">'list'</span> &#125;)</span><br><span class="line">  );</span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'test'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> done </span>) </span>&#123;</span><br><span class="line">  gulp.src([ allTestFiles ])</span><br><span class="line">    .pipe( g.istanbul() )</span><br><span class="line">    .on( <span class="string">'finish'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      gulp.src([ allTestFiles ])</span><br><span class="line">      .pipe( g.mocha() )</span><br><span class="line">      .on( <span class="string">'error'</span>, done )</span><br><span class="line">      .pipe( g.istanbul.writeReports() )</span><br><span class="line">      .on( <span class="string">'end'</span>, done );</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'default'</span>, [ <span class="string">'assets'</span> ], <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  gulp.watch([ allTestFiles, <span class="string">'src/ajax.js'</span> ], [ <span class="string">'test'</span> ]);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>E Enfim, nosso ‘index.html’: </p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">title</span>&gt;</span>Ajax module in VanillaJS<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"public/mocha.css"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">"mocha"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"src/ajax.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"public/chai.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"public/mocha.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript">mocha.setup(<span class="string">'bdd'</span>)</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"tests/test.ajax.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined">mocha.run()</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>Acessando essa <code>index.html</code> no seu navegador, você terá acesso à todos os testes, podendo acompanhá-los à medida em que forem sendo implementados :)</p><h2 id="Detalhes-do-metodo"><a href="#Detalhes-do-metodo" class="headerlink" title="Detalhes do método"></a>Detalhes do método</h2><p>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.</p><p>Basicamente, nós queremos que nosso módulo utilize Ajax (<a href="https://developer.mozilla.org/pt-BR/docs/Web/API/XMLHttpRequest" target="_blank" rel="noopener">XMLHttpRequest</a>), e que ele responda aos métodos <code>get</code>, <code>post</code>, <code>put</code> e <code>delete</code>.</p><p>A resposta deve vir no formato de <strong>Promises</strong>, com os métodos <code>done</code> e <code>error</code>.</p><p>Esse será nosso <a href="http://pt.wikipedia.org/wiki/Produto_vi%C3%A1vel_m%C3%ADnimo" target="_blank" rel="noopener">MVP</a>.</p><p>Já pode colocar o <strong>Gulp</strong> pra rodar e ficar assistindo nossos arquivos, com o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp</span><br></pre></td></tr></table></figure><h2 id="Usando-o-padrao-UMD"><a href="#Usando-o-padrao-UMD" class="headerlink" title="Usando o padrão UMD"></a>Usando o padrão UMD</h2><p>Para que nosso módulo funcione corretamente com CommonJS, AMD ou sem nenhum padrão de módulos específico, precisamos usar o formato <a href="https://blog.da2k.com.br/2015/01/05/como-criar-componentes-js-usando-modulos-amd-commonjs-e-umd-parte-3-3/"><strong>UMD</strong></a>.</p><p>Nosso módulo <code>src/ajax.js</code> iniciará com a seguinte estrutura:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">;(<span class="function"><span class="keyword">function</span> (<span class="params"> root, factory </span>) </span>&#123;</span><br><span class="line"><span class="meta">  'use strict'</span>;</span><br><span class="line">  <span class="comment">/* istanbul ignore next */</span></span><br><span class="line">  <span class="keyword">if</span> ( <span class="keyword">typeof</span> define === <span class="string">'function'</span> &amp;&amp; define.amd ) &#123;</span><br><span class="line">    define( <span class="string">'Ajax'</span>, factory );</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span> ( <span class="keyword">typeof</span> exports === <span class="string">'object'</span> ) &#123;</span><br><span class="line">    exports = <span class="built_in">module</span>.exports = factory();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">else</span> &#123;</span><br><span class="line">    root.Ajax = factory();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)(<span class="keyword">this</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line"><span class="meta">  'use strict'</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">Ajax</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> $public = &#123;&#125;;</span><br><span class="line">    <span class="keyword">var</span> $private = &#123;&#125;;</span><br><span class="line">  </span><br><span class="line">    <span class="keyword">return</span> $public;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">return</span> Ajax;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Das linhas <code>1</code> a <code>13</code>, aplicamos o <strong>UMD</strong>. Agora nosso módulo é Universal :D</p><p>O comentário na linha <code>3</code>, é para que o <strong>Istanbul</strong> ignore esse <code>if</code>, pois não teremos os <code>3</code> 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.</p><p><strong>Observação importante:</strong> </p><p>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 <strong>UMD</strong>, você precisa, ao menos, garantir manualmente que tudo funciona. Não adianta comentar todo o código para que o <em>Istanbul</em> ignore, pois você estará enganando a si mesmo. Use essa feature com cautela.</p><h2 id="Iniciando-os-testes"><a href="#Iniciando-os-testes" class="headerlink" title="Iniciando os testes"></a>Iniciando os testes</h2><p>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 <code>get</code>, <code>post</code>, <code>put</code> e <code>delete</code>.</p><p>Vamos então criar o teste para isso. A base do nosso arquivo <code>tests/test.ajax.js</code> ficará assim:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">;(<span class="function"><span class="keyword">function</span> (<span class="params"> root, factory </span>) </span>&#123;</span><br><span class="line"><span class="meta">  'use strict'</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">if</span> ( <span class="keyword">typeof</span> define === <span class="string">'function'</span> &amp;&amp; define.amd ) &#123;</span><br><span class="line">    define( <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="built_in">require</span>([ <span class="string">'Ajax'</span> ]);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">else</span> <span class="keyword">if</span> ( <span class="keyword">typeof</span> exports === <span class="string">'object'</span> ) &#123;</span><br><span class="line">    exports = <span class="built_in">module</span>.exports = factory( <span class="built_in">require</span>( <span class="string">'chai'</span> ).should(), <span class="built_in">require</span>( <span class="string">'../src/ajax'</span> ) );</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">else</span> &#123;</span><br><span class="line">    root.Ajax = factory( root.chai.should(), root.Ajax );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)(<span class="keyword">this</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> should, Ajax </span>) </span>&#123;</span><br><span class="line"><span class="meta">  'use strict'</span>;</span><br><span class="line">  </span><br><span class="line">  describe( <span class="string">'Test module interface'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    it( <span class="string">'Should have `get` method'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> ajax = <span class="keyword">new</span> Ajax();</span><br><span class="line">      ajax.should.have.property( <span class="string">'get'</span> );</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Vamos adicionar o <strong>UMD</strong> também para o nosso teste, pois ele ficará rodando no terminal, com <strong>Node</strong>. Assim nós poderemos acompanhar os resultados tanto no browser, como no terminal :)</p><p>Incluímos a biblioteca <a href="http://chaijs.com/" target="_blank" rel="noopener">Chai</a>, para fazer as asserções dos nossos testes.</p><p>Na linha <code>18</code>, damos início ao teste:</p><p>O <code>describe</code> vai criar um <code>wrapper</code> com vários testes de uma parte específica do módulo. Nesse primeiro <code>describe</code>, vamos testar a <em>interface</em> do módulo.</p><p>Nosso primeiro teste, na linha <code>19</code>, diz que nosso módulo “Deveria ter um método chamado <strong>get</strong>“.</p><p>Instanciamos o objeto do nosso módulo - <code>new Ajax()</code> - e fazemos a asserção, verificando se a propriedade <code>get</code> existe.</p><p>E o nosso teste quebra, pois esse método não existe:</p><p><img src="/uploads/2015/03/method-get-doesnt-exist.png" alt=""></p><p>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 <span style="color: red">RED</span>.</p><p>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 (<em>baby steps</em>):</p><p>Adicionamos então ao nosso arquivo <code>src/ajax.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line"><span class="keyword">var</span> $public = &#123;&#125;;</span><br><span class="line">  </span><br><span class="line">$public.get = <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>Pronto, agora temos um método <code>get</code>! Vamos ver se nosso teste passou?</p><p><img src="/uploads/2015/03/method-get-pass.png" alt=""></p><p>Agora sim! Temos o <span style="color: green">GREEN</span>, pois nosso teste passou. </p><p>Podemos ainda acompanhar no terminal como está a cobertura do nosso código:</p><p><img src="/uploads/2015/03/code-coverage-ajax-module.jpg" alt=""></p><p>Como estamos usando TDD, a tendência é que tenhamos sempre 100% do nosso código coberto por testes! :D</p><p>O próximo passo é o <span style="color: blue">BLUE</span>, ou <strong>Refactory</strong>. Nesse caso, não precisamos refatorar nosso código, pois não tem nada a ser refatorado.</p><p>Com o passar dos testes, dependendo do <em>baby step</em> que nós utilizarmos, precisaremos refatorar o código para que ele se mantenha em ordem. O passo do <em>refactory</em> serve somente para limpar o código já existente. Você nunca deve incluir nenhuma funcionalidade a mais no momento do <em>refactory</em>. Os testes que passam devem continuar passando, mas a leitura do código deve ser melhor do que você deixou da última vez :)</p><p>Curioso para ver como isso continua? Então aguarde o <a href="https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/">próximo post</a>! :D</p><p>Fica como lição de casa pra você fazer os outros 3 testes com os métodos <code>post</code>, <code>put</code> e <code>delete</code>!</p><p>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 <strong>Promises</strong>.</p><p>Ficou com dúvidas? Comentae!</p><p>Até lá!</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;/uploads/2015/03/ajax-module-with-promises.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;No &lt;a href=&quot;https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/&quot;&gt;artigo anterior&lt;/a&gt;, você viu como as &lt;strong&gt;Promises&lt;/strong&gt; resolvem o problema de &lt;em&gt;callback hell&lt;/em&gt;. Agora vamos ver na prática como criar nossas próprias &lt;strong&gt;Promises&lt;/strong&gt;!&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="ajax" scheme="https://blog.da2k.com.br/tags/ajax/"/>
    
  </entry>
  
  <entry>
    <title>Javascript - entendendo e criando suas próprias Promises</title>
    <link href="https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/"/>
    <id>https://blog.da2k.com.br/2015/03/05/javascript-entendendo-e-criando-suas-proprias-promises/</id>
    <published>2015-03-05T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.862Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/promises.jpg" alt=""></p><p>Você já deve ter ouvido falar sobre <strong>Promises</strong>, e provavelmente sabe do problema que elas resolvem. Mas você sabe como implementar suas próprias <strong>Promises</strong>? Vamos ver como fazer isso na prática! </p><a id="more"></a><h2 id="O-problema-callback-hell"><a href="#O-problema-callback-hell" class="headerlink" title="O problema - callback hell"></a>O problema - callback hell</h2><p>Sempre que você precisa executar uma ação após uma requisição assíncrona, normalmente o código vai se parecer com isso:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">obj.asyncFunction(<span class="function"><span class="keyword">function</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">  response.asyncFunction(<span class="function"><span class="keyword">function</span>(<span class="params"> response2 </span>) </span>&#123;</span><br><span class="line">    response2.asyncFunction(<span class="function"><span class="keyword">function</span>(<span class="params"> response3 </span>) </span>&#123;</span><br><span class="line">      response3.asyncFunction(<span class="function"><span class="keyword">function</span>(<span class="params">response4 </span>) </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> response4;</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Esse é o famoso <strong>callback hell</strong>, onde você depende do retorno de cada requisição para iniciar a próxima! Parece que o <em>Ryu</em> está dando uma hadouken ali!</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/hadouken.jpg" alt=""></p><p><em>Como resolver?</em></p><h2 id="Solucao-1-Metodos-acoplados"><a href="#Solucao-1-Metodos-acoplados" class="headerlink" title="Solução 1: Métodos acoplados"></a>Solução 1: Métodos acoplados</h2><p>Você pode resolver o <strong>callback hell</strong> usando métodos acoplados, ou seja, um método que vai depender de outro como resposta:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">obj.asyncFunction( responseFunc );</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">responseFunc</span>(<span class="params"> response </span>) </span>&#123;</span><br><span class="line">  response.asyncFunction( responseFunc2 );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">responseFunc2</span>(<span class="params"> response2 </span>) </span>&#123;</span><br><span class="line">  response2.asyncFunction( responseFunc3 );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">responseFunc3</span>(<span class="params"> response3 </span>) </span>&#123;</span><br><span class="line">  response3.asyncFunction( responseFunc4 );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">responseFunc4</span>(<span class="params"> response4 </span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> response4;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Isso já ajuda a resolver o problema do <strong>callback hell</strong>. Mas tem uma forma ainda mais elegante: <strong>Promises</strong>!</p><h2 id="Solucao-2-Promises"><a href="#Solucao-2-Promises" class="headerlink" title="Solução 2: Promises"></a>Solução 2: Promises</h2><p>As <strong>Promises</strong>, como o próprio nome diz, são <em>promessas</em> de que você terá um resultado ao final da requisição. Um exemplo é o método <code>$.get</code> do jQuery. Você passa a URL onde você vai buscar seus dados para esse método, e, ao finalizar, você pode utilizar os métodos <code>done()</code>, para saber se o retorno foi bem sucedido, <code>fail()</code> para erro e <code>always()</code> para o final da requisição, independente de sucesso ou erro.</p><p>Dessa forma, você consegue utilizar algo como:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">$.get( <span class="string">'http://myapp.com/api/data'</span> )</span><br><span class="line">.done(<span class="function"><span class="keyword">function</span>(<span class="params"> data </span>) </span>&#123;</span><br><span class="line">  <span class="comment">// =&gt; retorno com sucesso!</span></span><br><span class="line">&#125;)</span><br><span class="line">.fail(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// =&gt; retorno com erro!</span></span><br><span class="line">&#125;)</span><br><span class="line">.always(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// =&gt; final da requisição!</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>Assim você remove o acoplamento de várias funções, e usa métodos encadeados. :)</p><p>Essa é a ideia inicial da utilização de <strong>Promises</strong>. Nos próximos artigos, vamos construir um módulo que faz requisições <strong>Ajax</strong>, parecido com esse do jQuery, mas implementando nossas próprias <strong>Promises</strong> de <em>success</em> e <em>error</em> para os verbos <em>get</em>, <em>post</em>, <em>put</em> e <em>delete</em>. Esse nosso módulo será todo <a href="https://blog.da2k.com.br/2015/01/06/pensando-tdd-com-javascript/">coberto por testes</a>, então se prepare para uma grande aventura :D</p><p>Até lá!</p><h2 id="Proximos-artigos-dessa-serie"><a href="#Proximos-artigos-dessa-serie" class="headerlink" title="Próximos artigos dessa série:"></a>Próximos artigos dessa série:</h2><ul><li><a href="https://blog.da2k.com.br/2015/03/06/javascript-criando-um-modulo-ajax-com-promises/">Parte 1</a></li><li><a href="https://blog.da2k.com.br/2015/03/08/javascript-criando-um-modulo-ajax-com-promises-parte-2/">Parte 2</a></li><li><a href="https://blog.da2k.com.br/2015/03/11/javascript-criando-um-modulo-ajax-com-promises-parte-3/">Parte 3</a></li><li><a href="https://blog.da2k.com.br/2015/03/14/javascript-criando-um-modulo-ajax-com-promises-parte-4/">Parte 4</a></li><li><a href="https://blog.da2k.com.br/2015/03/22/javascript-criando-um-modulo-ajax-com-promises-parte-5/">Parte 5</a></li></ul><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/promises.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Você já deve ter ouvido falar sobre &lt;strong&gt;Promises&lt;/strong&gt;, e provavelmente sabe do problema que elas resolvem. Mas você sabe como implementar suas próprias &lt;strong&gt;Promises&lt;/strong&gt;? Vamos ver como fazer isso na prática! &lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="promises" scheme="https://blog.da2k.com.br/tags/promises/"/>
    
      <category term="tdd" scheme="https://blog.da2k.com.br/tags/tdd/"/>
    
  </entry>
  
  <entry>
    <title>Stylus - Palavras chave em argumentos</title>
    <link href="https://blog.da2k.com.br/2015/03/04/stylus-palavras-chave-em-argumentos/"/>
    <id>https://blog.da2k.com.br/2015/03/04/stylus-palavras-chave-em-argumentos/</id>
    <published>2015-03-04T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.874Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/keyword-arguments.png" alt=""></p><p>Já vimos como é fácil criar <a href="https://blog.da2k.com.br/2015/02/17/stylus-usando-mixins/"><em>mixins</em></a> e <a href="https://blog.da2k.com.br/2015/02/26/stylus-o-poder-das-funcoes/"><em>functions</em></a> no <strong>Stylus</strong>. Mas como os parâmetros podem ser passados para obtermos os resultados esperados? Vem comigo que eu te mostro ;)</p><a id="more"></a><p>O <strong>Stylus</strong> suporta <em>keyword arguments</em>, ou <em>“kwargs”</em>. Isso significa que você não precisa manter a mesma ordem dos parâmetros quando invocar uma <em>function</em> ou um <em>mixin</em>, e inclusive pode fazer algumas variações um bastante diferentes. Vamos ver nos exemplos para ficar mais claro:</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: rgba(<span class="number">255</span>, <span class="number">200</span>, <span class="number">100</span>, <span class="number">0.5</span>);</span><br><span class="line">  <span class="attribute">color</span>: rgba(red: <span class="number">255</span>, green: <span class="number">200</span>, blue: <span class="number">100</span>, alpha: <span class="number">0.5</span>);</span><br><span class="line">  <span class="attribute">color</span>: rgba(alpha: <span class="number">0.5</span>, blue: <span class="number">100</span>, red: <span class="number">255</span>, <span class="number">200</span>);</span><br><span class="line">  <span class="attribute">color</span>: rgba(alpha: <span class="number">0.5</span>, blue: <span class="number">100</span>, <span class="number">255</span>, <span class="number">200</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Que irá compilar:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">rgba</span>(255,200,100,0.5);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">rgba</span>(255,200,100,0.5);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">rgba</span>(255,200,100,0.5);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">rgba</span>(255,200,100,0.5);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Se você ainda não conhece o <strong>Stylus</strong>, recomendo que leia o <a href="https://blog.da2k.com.br/2015/02/15/escrevendo-css-com-stylus/">primeiro artigo da série</a>, para que você possa montar seu ambiente e colocar o <strong>Stylus</strong> pra rodar :)</p><p>O <strong>Stylus</strong> tem uma função embutida (_Built-in Function), chamada <code>rgba</code>, que retorna o valor <code>CSS</code> para <code>rgba</code>.</p><p>Essa função aceita 4 parâmetros: <code>red</code>, <code>green</code>, <code>blue</code> e <code>alpha</code>. Como você pode ver no exemplo acima, na primeira chamada de <code>color</code>, fazemos no padrão do <strong>CSS</strong>, chamando os parâmetros na ordem em que eles devem ser chamados.</p><p>Na segunda chamada de <code>color</code>, nós nomeamos os parâmetros, ainda mantendo a ordem. E, como você pode ver, a compilação é a mesma.</p><p>Agora olhe que loucura: na terceira chamada, os parâmetros não estão em ordem, mas ainda assim as coisas compilam como deveriam, pois o <strong>Stylus</strong> sabe exatamente onde deve colocar cada valor, pois nomeamos os argumentos!</p><p>E mais interessante: perceba que o último argumento não está nomeado!</p><p><em>Então como o <strong>Stylus</strong> sabe onde deve ir esse valor?</em></p><p>Como já tinhamos nomeado <code>alpha</code>, <code>blue</code> e <code>red</code>, o único argumento que sobrou foi o <code>green</code>. Logo, esse valor só pode ser dele ;)</p><p>Agora veja a quarta chamada: temos somente dois valores nomeados. Quando isso acontece, o <strong>Stylus</strong> atribui os valores dos argumentos nomeados, e os que não estão nomeados, ele coloca na ordem em que deveriam ser chamados na <em>function</em> ou <em>mixin</em>, excluindo apenas os que já foram passados com nome.</p><p>Olhe novamente para a última chamada:</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">color</span>: rgba(alpha: <span class="number">0.5</span>, blue: <span class="number">100</span>, <span class="number">255</span>, <span class="number">200</span>);</span><br></pre></td></tr></table></figure><p>Os valores para <code>alpha</code> e <code>blue</code> o <strong>Stylus</strong> já tem. A ordem para passar os parâmetros é:</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">rgba</span><span class="params">(red, green, blue, alpha)</span></span></span><br></pre></td></tr></table></figure><p>Então ainda faltam os valores para <code>red</code> e <code>green</code>, que receberão, respectivamente, os próximos valores :D</p><p><em>Mas como eu faço para saber qual a ordem que eu devo passar os parâmetros?</em></p><p>O <strong>Stylus</strong> tem uma função chamada <code>p()</code>, que retorna como o <em>mixin</em> ou a <em>function</em> foram criados.</p><p>Se você colocar no seu arquivo <strong>Stylus</strong>:</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">p</span><span class="params">(rgba)</span></span></span><br></pre></td></tr></table></figure><p>Você terá como retorno no seu terminal:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">inspect: rgba(red, green, blue, alpha)</span><br></pre></td></tr></table></figure><p>E isso funciona também para os <em>mixins</em> e <em>functions</em> criados por você! :D</p><p>Da hora não?</p><p>Aproveite essa incrível ferramenta e até o próximo artigo :)</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/keyword-arguments.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Já vimos como é fácil criar &lt;a href=&quot;https://blog.da2k.com.br/2015/02/17/stylus-usando-mixins/&quot;&gt;&lt;em&gt;mixins&lt;/em&gt;&lt;/a&gt; e &lt;a href=&quot;https://blog.da2k.com.br/2015/02/26/stylus-o-poder-das-funcoes/&quot;&gt;&lt;em&gt;functions&lt;/em&gt;&lt;/a&gt; no &lt;strong&gt;Stylus&lt;/strong&gt;. Mas como os parâmetros podem ser passados para obtermos os resultados esperados? Vem comigo que eu te mostro ;)&lt;/p&gt;
    
    </summary>
    
      <category term="css" scheme="https://blog.da2k.com.br/categories/css/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="stylus" scheme="https://blog.da2k.com.br/tags/stylus/"/>
    
      <category term="pré-processadores" scheme="https://blog.da2k.com.br/tags/pre-processadores/"/>
    
  </entry>
  
  <entry>
    <title>Gerenciando corretamente dependências em NodeJS - save ou save-dev?</title>
    <link href="https://blog.da2k.com.br/2015/03/03/gerenciando-corretamente-dependencias-em-nodejs-save-ou-save-dev-1/"/>
    <id>https://blog.da2k.com.br/2015/03/03/gerenciando-corretamente-dependencias-em-nodejs-save-ou-save-dev-1/</id>
    <published>2015-03-03T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.854Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/save-or-save-dev.png" alt=""></p><p><em>Quando eu instalo um módulo do <strong>NodeJS</strong>, devo usar <strong>–save</strong> ou <strong>–save-dev</strong>? E porque eu tenho as duas opções?</em></p><p>Vem descobrir ;)</p><a id="more"></a><p>Post curto, mas pra sanar a dúvida de uma vez por todas:</p><p><em>–save ou –save-dev?</em></p><p>Em <strong>NodeJS</strong>, quando você está utilizando algum módulo que não faz parte do <strong>core</strong>, você precisa instalá-lo com o comando <code>npm install</code>, ou <code>npm i</code>. E para que você possa facilmente reinstalar esses módulos em vários ambientes diferentes, sem precisar ficar lembrando quais você utilizou, ou fazendo isso manualmente, você cria um arquivo na raiz do seu projeto chamado <code>package.json</code> - que pode ser criado a partir do comando <code>npm init</code>, e respondendo a algumas perguntas - que irá gerenciar todas as dependências do seu projeto.</p><p>Quando você instala um módulo utilizando a flag <code>--save</code>, o módulo é salvo em <code>dependencies</code>, dentro do <code>package.json</code>.</p><p>Por exemplo: no nosso projeto, nós iremos utilizar o <strong>express</strong> e o <strong>mongoose</strong>. O <strong>Express</strong> é um web framework que irá nos ajudar a facilitar nosso trabalho ao trabalhar com aplicações web no <strong>NodeJS</strong>. Já o <strong>mongoose</strong> é um módulo que vai nos ajudar a modelar nossa base de dados, criada em <strong>Mongo DB</strong>. Para instalá-lo, você vai utilizar o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save express mongoose</span><br></pre></td></tr></table></figure><p>E ele fica salvo no <code>package.json</code>, assim:</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">"dependencies" : &#123;</span><br><span class="line">  "express": "^4.12.2",</span><br><span class="line">  "mongoose": "^3.8.24"</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Aqui você usa o <code>--save</code>, pois esses dois módulos são uma dependência do seu projeto. Você precisa deles em produção, senão a sua aplicação não funciona.</p><p>Agora imagine a seguinte situação: você precisa fazer testes unitários na sua aplicação, e vai utilizar o <strong>Mocha</strong> para criar a base dos testes, e o <strong>Chai</strong> para fazer as asserções. Você usa <code>--save</code> ou <code>--save-dev</code>?</p><p>A pergunta que deve ser feita antes de instalar é a seguinte: <em>Preciso desse módulo em produção? A minha aplicação funciona sem ele?</em></p><p>Se a resposta for “não” para a primeira pergunta, e “sim” para a segunda, você só irá precisar do módulo em ambiente de desenvolvimento. Logo, você pode utilizar o <code>--save-dev</code>:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev mocha chai</span><br></pre></td></tr></table></figure><p>E isso irá criar uma entrada <code>devDependencies</code> no seu package.json:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"devDependencies"</span>: &#123;</span><br><span class="line">  <span class="string">"chai"</span>: <span class="string">"^2.1.0"</span>,</span><br><span class="line">  <span class="string">"mocha"</span>: <span class="string">"^2.1.0"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Essas entradas servem basicamente para facilitar o seu trabalho. Sempre que você precisar reinstalar qualquer um desses módulos, você não precisa utilizar novamente o comando de instalação, deixando explícito o nome dos módulos. Pode usar somente <code>npm i</code>, que o <strong>NPM</strong> irá procurar o seu arquivo <code>package.json</code> e, ao encontrá-lo, irá baixar e instalar todas as dependências em <code>dependencies</code> e <code>devDependencies</code> pra você.</p><p>Agora você sabe que deve utilizar o <code>--save</code> somente para instalar módulos que serão usados em produção, e o <code>--save-dev</code> somente para módulos que serão usados no momento do desenvolvimento.</p><p>Mas executando o <code>npm i</code>, todos os módulos serão instalados. Imagine que você só quer que, quando estiver no seu servidor de produção, somente os módulos em <code>dependencies</code> sejam instalados, e os módulos em <code>devDependencies</code> sejam ignorados.</p><p>Para fazer isso, vocề pode utilizar o comando:<br><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --production</span><br></pre></td></tr></table></figure></p><p>Isso é bastante interessante se você estiver utilizando uma ferramenta de <strong>CI</strong>, por exemplo, onde o seu <em>build</em> compila toda a sua aplicação e disponibiliza em produção. Usando o comando acima, somente os módulos em <code>dependencies</code> serão instalados :D</p><hr><p><strong>UPDATE</strong></p><p>Como bem lembrado nos comentários pelo <a href="https://github.com/osmarcs" target="_blank" rel="noopener">Osmar</a>, se você setar a sua variável de ambiente <code>NODE_ENV</code> para <code>production</code>, e executar o <code>npm i</code>, somente as dependências de produção serão instaladas, sem a necessidade do <code>--production</code> ;)</p><hr><p>Espero que tenha ficado claro a diferença entre o <code>--save</code> e o <code>--save-dev</code>. Se ainda ficou alguma dúvida, poste nos comentários :D</p><p>Até o próximo!</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/save-or-save-dev.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Quando eu instalo um módulo do &lt;strong&gt;NodeJS&lt;/strong&gt;, devo usar &lt;strong&gt;–save&lt;/strong&gt; ou &lt;strong&gt;–save-dev&lt;/strong&gt;? E porque eu tenho as duas opções?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Vem descobrir ;)&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="nodejs" scheme="https://blog.da2k.com.br/tags/nodejs/"/>
    
  </entry>
  
  <entry>
    <title>Gulp - Criando redirecionamentos com gulp-connect + connect-modrewrite</title>
    <link href="https://blog.da2k.com.br/2015/03/02/gulp-criando-redirecionamentos-com-gulp-connect-connect-modrewrite/"/>
    <id>https://blog.da2k.com.br/2015/03/02/gulp-criando-redirecionamentos-com-gulp-connect-connect-modrewrite/</id>
    <published>2015-03-02T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.854Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/gulp-modrewrite.png" alt=""></p><p>A situação é basicamente essa: Você está trabalhando em uma <strong>SPA</strong>, e usando <strong>Gulp</strong> para subir seu webserver. Você tem uma API Rest que foi feita em outra linguagem, e responde em outra porta. E o pior: essa aplicação não tem um <em>header</em> que previna o problema com <strong>CORS</strong>. Como resolver isso?</p><p>Vou te mostrar nesse post! Vem comigo :D</p><a id="more"></a><p>Na situação acima, você teria algumas URLs locais da API Rest para consultar, que na verdade, deveriam responder em outra porta. Vamos exemplificar.</p><h2 id="Estrutura-de-arquivos"><a href="#Estrutura-de-arquivos" class="headerlink" title="Estrutura de arquivos"></a>Estrutura de arquivos</h2><p>Primeiro precisamos criar nossa estrutura de arquivos. Crie um novo diretório e use o comando abaixo para criá-la:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir api app &amp;&amp; touch app/gulpfile.js app/index.html app/main.js api/app.js &amp;&amp; <span class="built_in">echo</span> <span class="string">"&#123;&#125;"</span> &gt; api/package.json &amp;&amp; <span class="built_in">echo</span> <span class="string">"&#123;&#125;"</span> &gt; app/package.json</span><br></pre></td></tr></table></figure><p>Que vai gerar a seguinte estrutura:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── api</span><br><span class="line">│   ├── app.js</span><br><span class="line">│   └── package.json</span><br><span class="line">└── app</span><br><span class="line">    ├── gulpfile.js</span><br><span class="line">    ├── index.html</span><br><span class="line">    ├── main.js</span><br><span class="line">│   └── package.json</span><br></pre></td></tr></table></figure><p>Agora, acesse o diretório <code>api</code>, e instale os módulos abaixo:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev connect connect-route</span><br></pre></td></tr></table></figure><h2 id="Criando-a-API-Rest"><a href="#Criando-a-API-Rest" class="headerlink" title="Criando a API Rest"></a>Criando a API Rest</h2><p>Feito isso, vamos criar a API Rest. No arquivo <code>api/app.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> connect = <span class="built_in">require</span>( <span class="string">'connect'</span> );</span><br><span class="line"><span class="keyword">var</span> connectRoute = <span class="built_in">require</span>( <span class="string">'connect-route'</span> );</span><br><span class="line"><span class="keyword">var</span> app = connect();</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> users = &#123;</span><br><span class="line">  joao: &#123; <span class="attr">name</span>: <span class="string">'João da Silva'</span>, <span class="attr">age</span>: <span class="number">30</span> &#125;,</span><br><span class="line">  maria: &#123; <span class="attr">name</span>: <span class="string">'Maria Firmina'</span>, <span class="attr">age</span>: <span class="number">26</span> &#125;,</span><br><span class="line">  paulo: &#123; <span class="attr">name</span>: <span class="string">'Paulo Torres'</span>, <span class="attr">age</span>: <span class="number">25</span> &#125;</span><br><span class="line">&#125;;</span><br><span class="line">  </span><br><span class="line">app.use( connectRoute( <span class="function"><span class="keyword">function</span>(<span class="params"> router </span>) </span>&#123;</span><br><span class="line">  router.get( <span class="string">'/api/users'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">    res.setHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/json'</span> );</span><br><span class="line">    res.end( <span class="built_in">JSON</span>.stringify( users ) );</span><br><span class="line">  &#125;);</span><br><span class="line">  </span><br><span class="line">  router.post( <span class="string">'/api/user/:slug'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"> req, res, next </span>) </span>&#123;</span><br><span class="line">    res.setHeader( <span class="string">'Content-Type'</span>, <span class="string">'application/json'</span> );</span><br><span class="line">    res.end( <span class="built_in">JSON</span>.stringify( users[ req.params.slug ] ) );</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;));</span><br><span class="line">  </span><br><span class="line">app.listen( <span class="number">3000</span> );</span><br></pre></td></tr></table></figure><p>Prometo que em breve eu escrevo um post só explicando como criar uma API Rest :)</p><p>Esse arquivo está bastante simples: incluímos nossos módulos <code>connect</code> e <code>connect-route</code>, criamos uma lista de usuários em <code>users</code> que irá responder às URLs: <code>/api/users</code> via <strong>GET</strong>, onde todos os usuários do objeto serão retornados; e <code>URL:</code>/api/user/:slug`, via <strong>POST</strong>.</p><p>Vamos ver se isso funciona? Execute dentro do diretório <code>api</code>:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node app.js</span><br></pre></td></tr></table></figure><p>E acesse no seu navegador: </p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:3000</span><br></pre></td></tr></table></figure><p>Se tudo deu certo, você deve ter um retorno como esse:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="string">"joao"</span>:&#123;<span class="string">"name"</span>:<span class="string">"João da Silva"</span>,<span class="string">"age"</span>:30&#125;,<span class="string">"maria"</span>:&#123;<span class="string">"name"</span>:<span class="string">"Maria Firmina"</span>,<span class="string">"age"</span>:26&#125;,<span class="string">"paulo"</span>:&#123;<span class="string">"name"</span>:<span class="string">"Paulo Torres"</span>,<span class="string">"age"</span>:25&#125;&#125;</span><br></pre></td></tr></table></figure><p>Ótimo, nosso método <strong>GET</strong> funciona! Agora vamos testar o <strong>POST</strong>! Para o Chrome, existe uma extensão chamada <strong>Postman</strong>. Instale-a para testarmos outros verbos <strong>HTTP</strong>.</p><p>Após fazer isso, vamos testar o <strong>POST</strong> da nossa API:</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/post-user.png" alt=""></p><p>Fazemos a requisição, via <strong>POST</strong>, para a URL <code>http://localhost:3000/api/user/joao</code>, e o resultado retornado é o objeto <code>joao</code>!</p><p>Pronto! Deixe a API executando e abra uma nova aba no seu terminal. Vamos agora subir o frontend da nossa aplicação em uma porta diferente, para testar um cenário real.</p><h2 id="Criando-o-frontend-da-aplicacao-que-consumira-o-Rest"><a href="#Criando-o-frontend-da-aplicacao-que-consumira-o-Rest" class="headerlink" title="Criando o frontend da aplicação que consumirá o Rest"></a>Criando o frontend da aplicação que consumirá o Rest</h2><p>Vamos começar instalando os módulos do <strong>Gulp</strong> necessários:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev gulp gulp-connect</span><br></pre></td></tr></table></figure><p>Vamos somente subir nosso servidor, por enquanto. No arquivo <code>app/gulpfile.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>( <span class="string">'gulp'</span> );</span><br><span class="line"><span class="keyword">var</span> connect = <span class="built_in">require</span>( <span class="string">'gulp-connect'</span> )();</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'watch'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// task watch</span></span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'connect'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  connect.server(&#123;</span><br><span class="line">    root: <span class="string">'.'</span>,</span><br><span class="line">    port: <span class="number">3001</span></span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'default'</span>, [ <span class="string">'connect'</span>, <span class="string">'watch'</span> ]);</span><br></pre></td></tr></table></figure><p>E no arquivo <code>app/index.html</code>:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">title</span>&gt;</span>Test Gulp ModRewrite<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Test Gulp ModRewrite<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h2</span>&gt;</span>Users:<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">data-js</span>=<span class="string">"container"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  </span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"main.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>Agora, precisamos requisitar os dados à nossa API, para que eles sejam mostrados na nossa aplicação. No arquivo <code>app/main.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">;(<span class="function"><span class="keyword">function</span>(<span class="params"> win, doc, undefined </span>) </span>&#123;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">app</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> $private = &#123;&#125;;</span><br><span class="line">    <span class="keyword">var</span> $public = &#123;&#125;;</span><br><span class="line">    </span><br><span class="line">    $public.init = <span class="function"><span class="keyword">function</span> <span class="title">init</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      $private.getUsers();</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    $private.getUsers = <span class="function"><span class="keyword">function</span> <span class="title">getUsers</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">      xhr.open( <span class="string">'GET'</span>, <span class="string">'http://localhost:3000/api/users'</span> );</span><br><span class="line">      xhr.addEventListener( <span class="string">'readystatechange'</span>, $private.readyStateChange, <span class="literal">false</span> );</span><br><span class="line">      xhr.send();</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    $private.readyStateChange = <span class="function"><span class="keyword">function</span> <span class="title">readyStateChange</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">var</span> xhr = <span class="keyword">this</span>;</span><br><span class="line">      <span class="keyword">var</span> $container = doc.querySelector( <span class="string">'[data-js="container"]'</span> );</span><br><span class="line">      <span class="keyword">if</span>( xhr.readyState === <span class="number">4</span> ) &#123;</span><br><span class="line">        <span class="keyword">if</span>( xhr.status &gt;= <span class="number">200</span> &amp;&amp; xhr.status &lt; <span class="number">300</span> ) &#123;</span><br><span class="line">          $container.innerHTML = xhr.responseText;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> $public;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  app().init();</span><br><span class="line">&#125;)( <span class="built_in">window</span>, <span class="built_in">document</span> );</span><br></pre></td></tr></table></figure><p>Basicamente fazemos uma requisição Ajax à <code>http://localhost:3000/api/users</code>, via <strong>GET</strong>, tentando inserir o resultado no elemento <code>div[data-js=&quot;container&quot;]</code>, que colocamos na tela. E a resposta que nós temos é:</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/post-user-cors.png" alt=""></p><p>É isso que a gente merece mesmo! :(</p><p>Mas podemos contornar essa situação, usando um módulo chamado <code>connect-modrewrite</code>, (valeu <a href="https://github.com/caarlos0" target="_blank" rel="noopener">Becker</a> xD) que faz reescritas de URL, semelhante ao que você faz com o <code>.htaccess</code> em PHP, mas em NodeJS :D</p><p><em>Como faz?</em></p><p>Instale o módulo em <code>app/</code>:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev connect-modrewrite</span><br></pre></td></tr></table></figure><p>Agora, vamos configurá-lo no <code>app/gulpfile.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>( <span class="string">'gulp'</span> );</span><br><span class="line"><span class="keyword">var</span> connect = <span class="built_in">require</span>( <span class="string">'gulp-connect'</span> );</span><br><span class="line"><span class="keyword">var</span> modrewrite = <span class="built_in">require</span>( <span class="string">'connect-modrewrite'</span> );</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'watch'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// task watch</span></span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'connect'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  connect.server(&#123;</span><br><span class="line">    root: <span class="string">'.'</span>,</span><br><span class="line">    port: <span class="number">3001</span>,</span><br><span class="line">    middleware: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> [</span><br><span class="line">        modrewrite([ <span class="string">'/api/users http://localhost:3000/api/users [P]'</span> ])</span><br><span class="line">      ];</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;);</span><br><span class="line">  </span><br><span class="line">gulp.task( <span class="string">'default'</span>, [ <span class="string">'connect'</span>, <span class="string">'watch'</span> ]);</span><br></pre></td></tr></table></figure><p>Incluímos o módulo e adicionamos, no retorno do parâmetro <code>middleware</code>, dentro de <code>connect.server</code>, o código que vai fazer o <code>proxy</code> da nossa URL. Sempre que a nossa URL apontar para <code>/api/users</code>, na verdade será buscado o endereço <code>http://localhost:3000/api/users</code>.</p><p>Agora só precisamos alterar a URL no arquivo <code>app/main.js</code> de <code>http://localhost:3000/api/users</code> para <code>/api/users</code> e testar:</p><p><img src="https://blog.da2k.com.br/uploads/2015/03/post-user-cors-modrewrite.png" alt=""></p><p>E olha que loucura! Agora temos o resultado correto, e sem erros!</p><p>Esse módulo ajuda muito, principalmente nesses casos. Mas ele serve ainda para qualquer tipo de redirect que você precisar fazer :D</p><p>Era isso que eu queria mostrar hoje! Até o próximo post! :D</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/gulp-modrewrite.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A situação é basicamente essa: Você está trabalhando em uma &lt;strong&gt;SPA&lt;/strong&gt;, e usando &lt;strong&gt;Gulp&lt;/strong&gt; para subir seu webserver. Você tem uma API Rest que foi feita em outra linguagem, e responde em outra porta. E o pior: essa aplicação não tem um &lt;em&gt;header&lt;/em&gt; que previna o problema com &lt;strong&gt;CORS&lt;/strong&gt;. Como resolver isso?&lt;/p&gt;
&lt;p&gt;Vou te mostrar nesse post! Vem comigo :D&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="gulpjs" scheme="https://blog.da2k.com.br/tags/gulpjs/"/>
    
  </entry>
  
  <entry>
    <title>Gulp connect e livereload</title>
    <link href="https://blog.da2k.com.br/2015/03/01/gulp-connect-e-livereload/"/>
    <id>https://blog.da2k.com.br/2015/03/01/gulp-connect-e-livereload/</id>
    <published>2015-03-01T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.854Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/03/gulp-connect-livereload.png" alt=""></p><p>Hoje vamos ver como é simples subir um servidor web usando <strong>NodeJS</strong>, e ainda aproveitar as facilidades do <strong>Gulp</strong> para rodar nossas tarefas diárias, inclusive fazendo <strong>livereload</strong>! Quer ver como é fácil? Vem comigo :D</p><a id="more"></a><h2 id="Criando-a-estrutura-do-projeto"><a href="#Criando-a-estrutura-do-projeto" class="headerlink" title="Criando a estrutura do projeto"></a>Criando a estrutura do projeto</h2><p>Crie um diretório e execute dentro dele, no terminal:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch gulpfile.js index.html style.css &amp;&amp; <span class="built_in">echo</span> <span class="string">"&#123;&#125;"</span> &gt; package.json</span><br></pre></td></tr></table></figure><p>Isso irá criar a estrutura do nosso projeto:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── gulpfile.js</span><br><span class="line">├── index.html</span><br><span class="line">├── package.json</span><br><span class="line">└── style.css</span><br></pre></td></tr></table></figure><h2 id="Instalando-os-modulos-necessarios"><a href="#Instalando-os-modulos-necessarios" class="headerlink" title="Instalando os módulos necessários"></a>Instalando os módulos necessários</h2><p>Como de praxe, você precisa ter o <strong>NodeJS</strong> instalado, e o <strong>Gulp</strong>, instalado de modo global.</p><blockquote><p>O quê? Ainda não sabe como usar o <strong>Gulp</strong>? <a href="https://blog.da2k.com.br/2015/01/24/gulpjs-um-gole-de-otimizacao-no-seu-workflow/">Esse artigo</a> pode te ajudar a começar! Se quiser saber um pouco mais sobre essa incrível ferramenta, <a href="https://blog.da2k.com.br/tags/gulpjs/">aqui</a> você encontra várias coisas legais sobre ele ;)</p></blockquote><p>Vamos agora instalar os módulos necessários para os nossos testes. Execute no terminal, no diretório do seu projeto:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i --save-dev gulp gulp-connect</span><br></pre></td></tr></table></figure><p>Agora vamos configurar nosso <code>gulpfile.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>( <span class="string">'gulp'</span> );</span><br><span class="line"><span class="keyword">var</span> connect = <span class="built_in">require</span>( <span class="string">'gulp-connect'</span> );</span><br><span class="line"><span class="keyword">var</span> files = [ <span class="string">'index.html'</span>, <span class="string">'style.css'</span> ];</span><br><span class="line"></span><br><span class="line">gulp.task( <span class="string">'files'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  gulp.src( files ).pipe( connect.reload() );</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">gulp.task( <span class="string">'watch'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  gulp.watch( files, [ <span class="string">'files'</span> ]);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">gulp.task( <span class="string">'connect'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  connect.server(&#123; <span class="attr">livereload</span>: <span class="literal">true</span> &#125;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">gulp.task( <span class="string">'default'</span>, [ <span class="string">'connect'</span>, <span class="string">'watch'</span> ]);</span><br></pre></td></tr></table></figure><p>As tarefas são bastante simples. Nas linhas <code>3</code> e <code>4</code>, incluímos as dependências: <code>gulp</code> e <code>gulp-connect</code>. Na linha <code>5</code>, criamos um array com os arquivos que serão assistidos e, ao serem alterados, executarão o <code>livereload</code>.</p><p>Na linha <code>7</code>, criamos a task <code>files</code>, passamos como <em>source</em> o array já configurado na varável <code>files</code>, e chamamos o <code>connect.reload()</code>. Isso diz ao <code>connect</code> quais arquivos devem ser alterados para que ele faça o reload :)</p><p>Na linha <code>11</code>, criamos a task <code>watch</code>, que vai assistir os arquivos, para saber quando eles foram alterados.</p><p>Na linha <code>15</code>, criamos a task <code>connect</code>, que vai subir nosso servidor web. Por padrão, ao chamar <code>connect.server()</code>, ele vai usar a porta <code>8080</code>. Para subir em outra porta, passe um parâmetro <code>port</code> no objeto passado para esse método. No exemplo, estamos passando somente o parâmetro <code>livereload: true</code>, para que o <code>livereload</code> seja ativado.</p><p>Se quiser ver todas as opções do <code>gulp-connect</code>, você pode visitar a <a href="https://www.npmjs.com/package/gulp-connect" target="_blank" rel="noopener">documentação completa aqui</a>.</p><p>E, para finalizar, na linha <code>19</code>, criamos a task <code>default</code>, que executa as tasks <code>connect</code>, para subir o servidor, e a task <code>watch</code>, para assistir as mudanças nos arquivos <code>index.html</code> e <code>style.css</code>.</p><p>Agora execute no seu terminal o comando:</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gulp</span><br></pre></td></tr></table></figure><p>Abra no seu navegador, o endereço <code>http://localhost:8080</code> e você verá uma página em branco. Deixe o navegador e o seu editor lado a lado, e edite o arquivo <code>index.html</code>, colocando um conteúdo básico:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span> /&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">title</span>&gt;</span>Test Gulp Connect &amp; Livereload<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"style.css"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Gulp Connect &amp; Livereload<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><p>Ao salvar o arquivo, você já vai ver que, sem precisar recarregar a tela, o título <strong>Gulp Connect &amp; Livereload</strong> já irá aparecer!</p><p>Agora, brinque um pouco, editando o arquivo <code>style.css</code>, e veja a mágica acontecendo xD</p><p>Você pode usar qualquer estrutura de diretórios, e fazer o <code>livereload</code> funcionar para qualquer tipo de arquivo, desde que passe corretamente o caminho dos mesmos.</p><p>Bastante simples não? E não precisa adicionar nenhum script a mais na sua <code>index.html</code>! O <code>gulp-connect</code> já faz todo o trabalho sujo xD</p><p>Curtiu a dica? Já usa <strong>livereload</strong>? Tem algo a complementar? Compartilhe conosco nos comentários!</p><p>Até a próxima :D</p><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/03/gulp-connect-livereload.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Hoje vamos ver como é simples subir um servidor web usando &lt;strong&gt;NodeJS&lt;/strong&gt;, e ainda aproveitar as facilidades do &lt;strong&gt;Gulp&lt;/strong&gt; para rodar nossas tarefas diárias, inclusive fazendo &lt;strong&gt;livereload&lt;/strong&gt;! Quer ver como é fácil? Vem comigo :D&lt;/p&gt;
    
    </summary>
    
      <category term="javascript" scheme="https://blog.da2k.com.br/categories/javascript/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="gulpjs" scheme="https://blog.da2k.com.br/tags/gulpjs/"/>
    
  </entry>
  
  <entry>
    <title>WordPress - Criando um formulário de contato sem plugin - Parte 3</title>
    <link href="https://blog.da2k.com.br/2015/02/28/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-3/"/>
    <id>https://blog.da2k.com.br/2015/02/28/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-3/</id>
    <published>2015-02-28T00:00:00.000Z</published>
    <updated>2025-05-12T12:40:00.878Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://blog.da2k.com.br/uploads/2015/02/wordpress-form-without-plugin3.png" alt=""></p><p>Depois de aprendermos como <a href="https://blog.da2k.com.br/2015/02/22/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-1/">criar a <em>view</em></a> para o formulário, de forma que ela converse com o WP, e <a href="https://blog.da2k.com.br/2015/02/24/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-2/">inputar o resultado na tela</a>, agora é hora de tratar os dados e enviar o e-mail! <em>Follow-me!</em> :D</p><a id="more"></a><p>A primeira coisa a se fazer, é verificar se essas informações estão vindo através de um verbo <strong>POST</strong>, pois é assim que o nosso formulário foi configurado para enviar a mensagem. O usuário não deve visualizar nenhuma mensagem antes de executar a ação de enviar o formulário.</p><p>No arquivo <code>services/service-contact-form.php</code>, faça uma adição no método <code>send_contact_form()</code>:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> (object) <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'status'</span> =&gt; <span class="string">'success'</span>,</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="string">'Seu e-mail foi enviado com sucesso!'</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Pronto! Agora a mensagem só será mostrada se o campo <code>field_name</code> for enviado via <strong>POST</strong>. Poderíamos testar por qualquer campo do nosso formulário. Só não testamos por <code>!isset( $_POST )</code>, pois <code>$_POST</code> é uma superglobal do PHP, e está sempre disponível, ou seja, isso retornaria sempre <code>true</code>.</p><p>O próximo passo é verificar se todos os campos obrigatórios foram preenchidos:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    $all_fields = <span class="keyword">$this</span>-&gt;get_fields();</span><br><span class="line">    $are_all_fields_ok = <span class="keyword">$this</span>-&gt;are_all_fields_ok( $all_fields );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! $fields_its_ok ) &#123;</span><br><span class="line">        <span class="comment">// do something</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> (object) <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'status'</span> =&gt; <span class="string">'success'</span>,</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="string">'Seu e-mail foi enviado com sucesso!'</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Passamos para a variável <code>$all_fields</code> o retorno do método <code>get_fields()</code>. Ainda precisamos criá-lo. Depois, passamos para <code>$are_all_fields_ok</code> o retorno do método <code>are_all_fields_ok( $all_fields )</code>. Com isso, podemos verificar se todos os campos que deveriam estar preenchidos, foram feitos corretamente.</p><p>Vamos criar então o método `get_fields(), que retorna um array dos campos, com o valor dele, e se ele é obrigatório. Assim fica mais fácil e organizado para tratar os dados:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">get_fields</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    $fields = <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'name'</span> =&gt; <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'value'</span> =&gt; sanitize_text_field( $_POST[ <span class="string">'field_name'</span> ] ),</span><br><span class="line">            <span class="string">'is_required'</span> =&gt; <span class="keyword">true</span></span><br><span class="line">        ),</span><br><span class="line">        <span class="string">'email'</span> =&gt; <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'value'</span> =&gt; sanitize_email( $_POST[ <span class="string">'field_email'</span> ] ),</span><br><span class="line">            <span class="string">'is_required'</span> =&gt; <span class="keyword">true</span></span><br><span class="line">        ),</span><br><span class="line">        <span class="string">'subject'</span> =&gt; <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'value'</span> =&gt; sanitize_text_field( $_POST[ <span class="string">'field_subject'</span> ] ),</span><br><span class="line">            <span class="string">'is_required'</span> =&gt; <span class="keyword">false</span></span><br><span class="line">        ),</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'value'</span> =&gt; wp_kses( $_POST[ <span class="string">'field_message'</span> ], <span class="string">'br'</span> ),</span><br><span class="line">            <span class="string">'is_required'</span> =&gt; <span class="keyword">true</span></span><br><span class="line">        )</span><br><span class="line">    );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> $fields;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Se não estivéssemos obtendo o resultado de um <strong>POST</strong>, já teríamos retornado <code>false</code> na primeira verificação. Logo, podemos usar esse superglobal aqui com segurança. </p><p>Criamos o nosso método como <code>private</code>, pois não precisamos que ele seja acessado externamente. Basicamente o que esse método faz é criar um array com cada campo, onde o valor do campo é passado para <code>value</code> e se o campo é obrigatório ou não, é passado para <code>is_required</code>. O <strong>WordPress</strong> tem uma função chamada <code>sanitize_email()</code> (usada acima), que faz a limpeza dos caracteres do campo. Se houver qualquer tentativa de inserção de tags HTML, script, ou qualquer código malicioso, o valor não será enviado. Só serão aceitos caracteres válidos para um campo de e-mail. O mesmo para <code>sanitize_text_field()</code>.</p><p>Já a função <code>wp_kses()</code> - <a href="http://codex.wordpress.org/Function_Reference/wp_kses" target="_blank" rel="noopener"><em>KSES Strips Evil Scripts</em></a> - remove tags HTML. No segundo parâmetro você pode passar as tags permitidas. No nosso caso, vamos permitir somente quebras de linha (<code>br</code>).</p><p>Em posts futuros, falaremos com mais detalhes sobre essas funções. Por enquanto é isso que você precisa saber :)</p><p>Já criamos nosso método que retorna todos os campos, agora precisamos verificar se eles são válidos. Crie o método <code>are_all_fields_ok()</code>:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">are_all_fields_ok</span><span class="params">( $fields )</span> </span>&#123;</span><br><span class="line">    <span class="keyword">foreach</span>( $fields <span class="keyword">as</span> $field ) &#123;</span><br><span class="line">        <span class="keyword">if</span>( <span class="keyword">$this</span>-&gt;is_field_required_empty( $field ) ) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Fazemos um <code>foreach</code> para passar por todos os campos passados como parâmetro e, se algum campo obrigatório não estiver preenchido, retornamos <code>false</code>. Se todos os campos obrigatórios estiverem preenchidos, então retornamos <code>true</code>.</p><p>Perceba que aqui, para verificar se algum campo obrigatório está em branco, nós usamos o método <code>is_field_required_empty()</code>, passando como parâmetro o campo que está sendo iterado no <code>foreach</code>.</p><p>Vamos criar esse método?</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">is_field_required_empty</span><span class="params">( $field )</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> $field[ <span class="string">'is_required'</span> ] &amp;&amp; <span class="keyword">empty</span>( $field[ <span class="string">'value'</span> ] );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Pronto! Essa função verifica se nosso capo é obrigatório e se ele está vazio! Se estiver, então não devemos enviar o formulário! Vamos mostrar uma mensagem de erro ao usuário. Edite o método <code>send_contact_form()</code>:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    $all_fields = <span class="keyword">$this</span>-&gt;get_fields();</span><br><span class="line">    $are_all_fields_ok = <span class="keyword">$this</span>-&gt;are_all_fields_ok( $all_fields );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! $are_all_fields_ok ) &#123;</span><br><span class="line">        <span class="keyword">return</span> (object) <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'message'</span> =&gt; <span class="string">'Preencha todos os campos!'</span>,</span><br><span class="line">            <span class="string">'status'</span> =&gt; <span class="string">'error'</span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Se você tentar fazer o envio do formulário agora, sem preencher todos os campos obrigatórios, você irá ver a mensagem de erro :D</p><p><em>Legal! E agora, qual o próximo passo?</em></p><p>O próximo passo é verificar se não estamos <a href="https://blog.da2k.com.br/2015/02/16/acabando-com-spam-nos-seus-formularios/">recebendo algum SPAM</a>, testando aquele campo que deixamos oculto.</p><p>Vamos fazer primeiro a validação no nosso método <code>send_contact_form()</code>:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    $all_fields = <span class="keyword">$this</span>-&gt;get_fields();</span><br><span class="line">    $are_all_fields_ok = <span class="keyword">$this</span>-&gt;are_all_fields_ok( $all_fields );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! $are_all_fields_ok ) &#123;</span><br><span class="line">        <span class="keyword">return</span> (object) <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'message'</span> =&gt; <span class="string">'Preencha todos os campos!'</span>,</span><br><span class="line">            <span class="string">'status'</span> =&gt; <span class="string">'error'</span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( <span class="keyword">$this</span>-&gt;is_spam() ) &#123;</span><br><span class="line">        <span class="keyword">return</span> (object) <span class="keyword">array</span>(</span><br><span class="line">            <span class="string">'message'</span> =&gt; <span class="string">'Erro ao enviar mensagem. Tente novamente mais tarde.'</span>,</span><br><span class="line">            <span class="string">'status'</span> =&gt; <span class="string">'error'</span></span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>É hora de criar um outro método para verificação. Vamos chamá-lo de <code>is_spam()</code>, para verificar se tem algum robô engraçadinho tentando nos sacanear:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">is_spam</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( <span class="keyword">$this</span>-&gt;has_malicious_content() ||</span><br><span class="line">        <span class="keyword">$this</span>-&gt;has_more_than_three_links() ||</span><br><span class="line">        <span class="keyword">$this</span>-&gt;spam_field_is_filled()</span><br><span class="line">    ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">has_malicious_content</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> preg_match( <span class="string">'/bcc:|cc:|multipart|\[url|\[link|Content-Type:/i'</span>, implode( $_POST ) );</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">has_more_than_three_links</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> preg_match_all( <span class="string">'/&lt;a|http:/i'</span>, implode( $_POST ) ) &gt; <span class="number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">spam_field_is_filled</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> !<span class="keyword">empty</span>( $_POST[ <span class="string">'field_mail'</span> ] );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Criamos 3 novos métodos para verificação de <strong>SPAM</strong>: O método <code>has_malicious_content()</code>, irá verificar se foi inserido algo com <code>bcc:</code>, <code>cc:</code>, <code>multipart</code>, <code>[url</code>, <code>[link</code> e <code>Content-Type</code>, ignorando case sensitive (<code>/i</code>), em todos os campos.</p><p>O <code>has_more_than_three_links()</code>, verifica se existem mais de 3 links sendo enviados. Se você achar que 3 é muito, pode diminuir para o seu caso. Aqui usamos <code>preg_match_all</code> ao invés de <code>preg_match</code>, pois ele retorna a quantidade de vezes que um valor da regex foi encontrado;</p><p>E por último, mas não menos importante, temos o <code>spam_field_is_filled()</code>, onde verificamos o nosso campo de e-mail fake, pra saber se ele foi preenchido.</p><p>Se qualquer uma dessas condições for verdadeira, entendemos que estão tentando nos enviar <strong>SPAM</strong>, e ignoramos o envio, retornando <code>true</code> para <code>is_spam()</code>. Caso contrário, retornamos <code>false</code>.</p><p>Não precisamos do <code>else</code> pois, sempre que um valor é retornado (usando <code>return</code>), o PHP nem continua a leitura do que vem depois desse código. Assim deixamos também nosso método mais legível.</p><p>Bom, se olharmos para o nosso método principal, dá pra perceber que ele está um pouco verboso demais. Estamos retornando dois arrays (convertidos para objeto), com a mesma estrutura, mas que muda somente a mensagem interna. Vamos deixar isso mais organizado, e colocar essas mensagens também em um método. Até porque, ainda vamos precisar de mais uma mensagem: a de sucesso.</p><p>Editando então nosso método <code>send_contact_form()</code>:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    $all_fields = <span class="keyword">$this</span>-&gt;get_fields();</span><br><span class="line">    $are_all_fields_ok = <span class="keyword">$this</span>-&gt;are_all_fields_ok( $all_fields );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! $are_all_fields_ok ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'error'</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( <span class="keyword">$this</span>-&gt;is_spam() ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'error_sent'</span> );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Vamos obter, através de um método chamado <code>get_status_message()</code>, as mensagens de status, conforme o parâmetro passado para esse método.</p><p>Nosso método <code>get_status_message()</code> vai ficar assim:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">get_status_message</span><span class="params">( $status = <span class="string">'success'</span> )</span> </span>&#123;</span><br><span class="line">    $message = <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'success'</span> =&gt; <span class="keyword">$this</span>-&gt;get_status_message_success(),</span><br><span class="line">        <span class="string">'error'</span> =&gt; <span class="keyword">$this</span>-&gt;get_status_message_error(),</span><br><span class="line">        <span class="string">'error_sent'</span> =&gt; <span class="keyword">$this</span>-&gt;get_status_message_error_sent()</span><br><span class="line">    );</span><br><span class="line">    <span class="keyword">return</span> (object) $message[ $status ];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Não adianta nada tirar uma tripa de arrays do método principal e simplesmente jogar em outro método, concorda? Por isso, vamos criar um método para cada mensagem. Passamos como padrão o status <code>success</code>, ou seja, se esse método for chamado sem nenhum parâmetro, retornamos a mensagem de sucesso :)</p><p>No final, o array retornado é o objeto que precisamos na nossa view :D</p><p>Vamos ver como irão ficar esses 3 novos métodos com os status:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">get_status_message_success</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="string">'Mensagem enviada com sucesso!'</span>,</span><br><span class="line">        <span class="string">'status'</span> =&gt; <span class="string">'success'</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">get_status_message_error</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="string">'Preencha todos os campos!'</span>,</span><br><span class="line">        <span class="string">'status'</span> =&gt; <span class="string">'error'</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br><span class="line">  </span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">get_status_message_error_sent</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'message'</span> =&gt; <span class="string">'Erro ao enviar mensagem. Tente novamente mais tarde.'</span>,</span><br><span class="line">        <span class="string">'status'</span> =&gt; <span class="string">'error'</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Ah, agora sim! Bem melhor! Cada método fica pequeno, legível, e com uma responsabilidade única :)</p><p>Agora, se você tentar enviar o e-mail, preenchendo o campo de e-mail <em>fake</em>, vai receber uma mensagem de erro :D</p><p>Estamos quase lá! Vamos então fazer a última verificação: tentar enviar o e-mail, e verificar se este foi enviado com sucesso. No nosso método <code>send_contact_form()</code>, adicione:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">send_contact_form</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>( !<span class="keyword">isset</span>( $_POST[ <span class="string">'field_name'</span> ] ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    $all_fields = <span class="keyword">$this</span>-&gt;get_fields();</span><br><span class="line">    $are_all_fields_ok = <span class="keyword">$this</span>-&gt;are_all_fields_ok( $all_fields );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! $are_all_fields_ok ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'error'</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( <span class="keyword">$this</span>-&gt;is_spam() ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'error_sent'</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>( ! <span class="keyword">$this</span>-&gt;message_sent( $all_fields ) ) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'error_sent'</span> );</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;get_status_message( <span class="string">'success'</span> );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Nessa última verificação, vamos ver se a mensagem foi enviada corretamente. Invocamos o método <code>message_sent()</code>, passando os campos como parâmetro já dentro de um <code>if</code>, pois o retorno dele vai nos dizer se a mensagem foi enviada com sucesso ou não. </p><p>Se não foi, retornamos a mesma mensagem que é enviada quando o usuário tenta enviar um <strong>SPAM</strong>. Aqui você pode criar sua própria mensagem se preferir. Como é a mesma mensagem, poderíamos ter juntado, no mesmo <code>if</code> do <code>is_spam()</code>. Mas assim facilita a leitura, e você consegue ver exatamente quais passos estão sendo feitos antes de tentar enviar a mensagem.</p><p>E o último <code>return</code>, envia a mensagem com status de sucesso. Se não deu nenhum erro, quer dizer que foi tudo bem :)<br>O parâmetro <code>success</code> é opcional, pois deixamos setado como padrão no método <code>get_status_message()</code>. Vamos deixar assim só para ficar mais legível ;)</p><p>Vamos então criar nosso método que envia o e-mail:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">message_sent</span><span class="params">( $fields )</span> </span>&#123;</span><br><span class="line">    $to = <span class="string">'quem-recebe-o@email.com'</span>;</span><br><span class="line">    $subject = <span class="string">'E-mail enviado pelo site lalala.com.br - '</span> . $fields[ <span class="string">'subject'</span> ][ <span class="string">'value'</span> ];</span><br><span class="line">    $message = <span class="keyword">$this</span>-&gt;message_to_sent( $fields );</span><br><span class="line">    $headers = <span class="keyword">array</span>(</span><br><span class="line">        <span class="string">'Reply-To: '</span> . $fields[ <span class="string">'email'</span> ][ <span class="string">'value'</span> ]</span><br><span class="line">    );</span><br><span class="line">    $attachments = <span class="string">''</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> wp_mail( $to, $subject, $message, $headers, $attachments );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Aqui executamos o retorno da função <code>wp_mail()</code>, que retorna <code>true</code> se conseguiu enviar o e-mail, e false, caso contrário. Mas antes, nós configuramos algumas variáveis, até para saber a ordem correta dos parâmetros passados para a função <code>wp_mail()</code>.</p><p>O primeiro é o <code>$to</code>, que é o e-mail que vai receber a mensagem. O segundo, <code>$subject</code>, é o assunto do e-mail. No nosso formulário já tem esse campo, mas ele não é obrigatório. Vamos então deixar uma mensagem padrão antes de concatenar o valor desse campo, para que a gente saiba que o e-mail foi enviado pelo formulário de contato do site.</p><p>Como nós vamos configurar nossa mensagem para ser enviada em <strong>HTML</strong>, vamos colocá-la em um método separado, para não deixar esse muito grande.</p><p>Ainda podemos configurar alguns <code>$headers</code>, como <code>Reply-To:</code>, que é o e-mail para quem nós devemos responder, ao clicar no botão <strong>Responder</strong> do seu e-mail. Podemos também configurar para recebermos uma cópia (<code>Cc:</code>), ou cópia oculta (<code>Bcc:</code>) em outro e-mail. Se esse formulário envia e-mail para o seu cliente, é importante saber se os e-mails estão chegando corretamente, então você pode configurar esses campos de cópia. Ou ainda simplesmente para enviar para mais de uma pessoa de uma só vez.</p><p>Não vamos enviar nenhum anexo, então deixamos o <code>$attachments</code> em branco.</p><p>Agora só falta nosso método que gera a mensagem:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">message_to_sent</span><span class="params">( $fields )</span> </span>&#123;</span><br><span class="line">    $message  = sprintf( <span class="string">'&lt;h1&gt;Assunto: %s&lt;/h1&gt;'</span>, $fields[ <span class="string">'subject'</span> ][ <span class="string">'value'</span> ] );</span><br><span class="line">    $message .= sprintf( <span class="string">'&lt;h2&gt;De: %s&lt;/h2&gt;'</span>, $fields[ <span class="string">'email'</span> ][ <span class="string">'value'</span> ] );</span><br><span class="line">    $message .= sprintf( <span class="string">'&lt;h2&gt;Mensagem:&lt;/h2&gt;&lt;p&gt;%s&lt;/p&gt;'</span>, $fields[ <span class="string">'message'</span> ][ <span class="string">'value'</span> ] );</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> $message;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Um HTML simples, que retorna uma string com algumas tags, para deixar o e-mail mais organizado. Utilizamos <code>sprintf()</code> aqui para substituir os <code>%s</code>, passados na string. A partir do segundo parâmetro dessa função, o PHP começa a substituir cada <code>%s</code> por um desses parâmetros, nessa ordem.</p><p>No final, retornamos a string da mensagem :)</p><p>E assim nós terminamos nosso formulário de contato, com várias validações importantes, e sem precisar de plugin algum! Claro que poderíamos fazer muitas outras melhorias, como por exemplo, colocar um metabox na página de contato para que o cliente adicione os e-mails que ele quer usar para receber o contato, mas isso é assunto para outro post!</p><p>Até o próximo! :D</p><blockquote><p><strong>Link para o índice dessa série: </strong><br><a href="https://blog.da2k.com.br/2015/01/11/indice-da-serie-como-criar-temas-para-wordpress/">https://blog.da2k.com.br/2015/01/11/indice-da-serie-como-criar-temas-para-wordpress/</a></p><p><strong> Post anterior:</strong><br><a href="https://blog.da2k.com.br/2015/02/24/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-2/">https://blog.da2k.com.br/2015/02/24/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-2/</a></p><p><strong> Próximo post:</strong><br><a href="">EM BREVE!</a></p></blockquote><blockquote><p>Sobre o #1postperday: <a href="https://blog.da2k.com.br/2014/12/31/um-post-por-dia/">https://blog.da2k.com.br/2014/12/31/um-post-por-dia/</a></p></blockquote><blockquote><p>Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: <a href="https://github.com/fdaciuk/fdaciuk.github.io/issues/1" target="_blank" rel="noopener">https://github.com/fdaciuk/fdaciuk.github.io/issues/1</a></p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://blog.da2k.com.br/uploads/2015/02/wordpress-form-without-plugin3.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Depois de aprendermos como &lt;a href=&quot;https://blog.da2k.com.br/2015/02/22/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-1/&quot;&gt;criar a &lt;em&gt;view&lt;/em&gt;&lt;/a&gt; para o formulário, de forma que ela converse com o WP, e &lt;a href=&quot;https://blog.da2k.com.br/2015/02/24/wordpress-criando-um-formulario-de-contato-sem-plugin-parte-2/&quot;&gt;inputar o resultado na tela&lt;/a&gt;, agora é hora de tratar os dados e enviar o e-mail! &lt;em&gt;Follow-me!&lt;/em&gt; :D&lt;/p&gt;
    
    </summary>
    
      <category term="wordpress" scheme="https://blog.da2k.com.br/categories/wordpress/"/>
    
    
      <category term="1postperday" scheme="https://blog.da2k.com.br/tags/1postperday/"/>
    
      <category term="serie temas wordpress" scheme="https://blog.da2k.com.br/tags/serie-temas-wordpress/"/>
    
  </entry>
  
</feed>
