NODE OVERVIEW: Criando um servidor node.js do zero. Parte 2

Pedro Vallese
Nerdzão/Nerdgirlz
Published in
9 min readMar 26, 2019

Essa é a segunda parte do conteúdo em que eu explico node.js para iniciantes. A primeira parte é mais teórica, essa segunda parte é mais prática.

Vamos lá?

Talk is cheap, show me the code.

Primeiramente vamos trabalhar com o básico. Vamos fazer um servidor que recebe requisições sem nenhum conteúdo e retorna o famoso hello world.

var http = require('http');

http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World!');
}).listen(8080);

Se você não é acostumado com javascript, com certeza deve achar um tanto quanto estranho o código e como as instruções são executadas. Não tenha medo! Vamos explicar parte por parte:

var http = require('http');

Nesse trecho, você está pegando um objeto de uma biblioteca chamada http que é padrão do node.js.

http.createServer(function (req, res){...}).listen(8080)

Essa instrução fica mais fácil de ser lida se tirarmos o método a ser executado, basicamente o que ela faz é criar um servidor que fica na executa na porta 8080. O método passado para ela que foi minimizado somente é executado quando é feita uma requisição ao servidor.

function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World!')

Última parte é a função passada para o objeto criado. Ela irá receber como parâmetro a requisição e a resposta. Métodos oferecidos pelo cliente ao acessar o endereço. Ela simplesmente irá escrever no cabeçário que o conteúdo a ser recebido é um texto simples e depois o hello world é enviado para o cliente.
Muito simples não acha? Essa é a vantagem da tecnologia Node.

NPM

Junto com node, uma ferramenta de igual importância é o Node Package Manager, que funciona como um gerenciador de bibliotecas de forma que o programador consiga fazer download de qualquer dependência e gerenciá-la. Vamos começar o nosso projeto em uma pasta exclusiva e para registrar todas as bibliotecas que iremos usar, usaremos a instrução:

npm init

Consegue ver um novo arquivo no seu diretório? Esse arquivo é o seu package.json nele estará informação de todas as bibliotecas que você adquirir pelo npm para que fique mais fácil compartilhar tecnologias pela comunidade.

Agora vamos instalar o express, biblioteca importante para o nosso projeto, mais a frente seu uso será explicado.

npm install express

Agora, abra o package.json, está vendo a biblioteca instalada lá? Beleza! No git temos o package.json. Ao clonar o repositório apenas digite:

npm install

Pronto! Dessa forma todos os pacotes estão instalados! Você também pode ver os pacotes no arquivo node_modules.

Nossa API

Finalmente, vamos ao que interessa, construir nossa API, nesse exemplo iremos criar uma API que se comunica com open weather que nos fornecerá a temperatura e então disponibilizaremos para o usuário em uma página html. Então vamos lá!

Os arquivos de nosso projeto:

├── app
│ ├── model
│ │ └── temp.js
│ └── route.js
├── city.list.json
├── config
│ └── database.js
├── package.json
├── repos
│ └── querys.js
├── server.js
└── views
├── temperatura.ejs
└── temperatura_files

server.js

Neste é arquivo onde ficam todas as configurações do servidor e onde configuramos uma porta para ele. Na nossa aplicação existe apenas tês dependências:

Express: Biblioteca criada para criar códigos de comunicação http de forma rápida e eficiente. Note que nossa aplicação app é um objeto da biblioteca express.

Mongoose: Biblioteca de comunicação da nossa aplicação com o servidor node.

Ejs: Com essa tecnologia conseguimos mandar informações para a página html a ser renderizada para o cliente.

var port = process.env.PORT || 8080;

Isso faz parte de boas práticas, ao configurar uma porta para o servidor ficar na escuta você diz que primeiramente que ele deverá ficar em alguma já configurada pelo ambiente, caso contrário, monte a aplicação na 8080.

var configDB = require('./config/database.js');

Onde fica configurado a comunicação do banco de dados com a aplicação, é um simples JSON com uma url:

Nessa aplicação utilizaremos um banco de dados MongoDB que é um banco assíncrono e nosql, ideal para trabalhar com node.js. Não cabe aqui discutir as propriedades dele, nas referências deixarei um pouco de conteúdo sobre essa tecnologia. Para auxiliar a visualização do banco, sugiro a utilização do MongoDB Compass.

mongoose.connect(configDB.url,{useNewUrlParser: true});

Por fim, utilizaremos a string de conexão do nosso JSON para fazer a comunicação com o banco.

require(./app/route.js)(app);

Nossa chamada para outro módulo onde faremos o roteamento das requisições feitas, notem que é passado por parâmetro a nossa aplicação express.

route.js

Nossa aplicação é extremamente simples, temos apenas um endereço e dois métodos, um get e outro post.

De grosso modo, o nosso método POST consome os dados da Open Weather API e insere no nosso banco. O método GET puxa o último dado inserido e mostra em uma simples tela.

Vamos primeiramente ao nosso método Post.

app.post('/',function(req,res){...})

Para declarar para o servidor quais métodos e qual endereço você irá receber, primeiramente sua aplicação express (lembra que passamos ela como parâmetro quando chamamos o módulo route.js?) é chamada seguida do tipo de requisição, nesse caso, POST. O primeiro parâmetro é o endereço correspondente a essa requisição “/”, já o segundo parâmetro é a função a ser executada toda vez que alguém faça a requisição declarada. Note que ela recebe req e res , que são respectivamente a requisição feita pelo usuário e a resposta que o servidor irá devolver.

Antes de explicar as regras de negócio que serão executadas a partir da requisição, é importante primeiro, entender um pouco como funciona a API Open Weather: De grosso modo, vamos acessar o seguinte endereço:

http://api.openwaethermap.org/data/2.5/forecast?id=”+id+&APPID="+APPID

Observe os dois parâmetros enviados logo após “?” um é o id das cidades e o outro é o APPID que seria a chave de usuário, para criar uma chave APPID, só se inscrever no site e fazer a requisição de uma chave própria.

Primeira coisa a perceber é o parâmetro “id” e “APPID” enviados via url.

var id = req.query.id

var APPID = req.query.id;

Ou seja, nosso endereço de requisição, considerando que o nosso servidor seja local será:

http://localhost/?id=123&appid=321

No caso os dois parâmetros são números fictícios usados para ilustrar como seriam passados.

request("http//api.openweathermap.org/data/2.5/forecast?id="+id+"&APPID="+APPID,{json:true},(err,resp,body} => ...

Request é uma biblioteca padrão do node.js, com ela, é possível que seu servidor faça requisições, ao chamar a função request passamos o endereço seguido dos parâmetros (id e APPID), um JSON com informações do sistema. (nesse caso é dito que essa requisição pode receber objetos json como resposta, e por fim uma função, dessa vez representada por uma arrow function, que recebe como parâmetros: erro, resposta e requisição.

Por fim, no corpo da resposta há diversas informações, para acessá-las utilizamos res.body nesse caso, vamos pegar a temperatura e a data da previsão do primeiro item da lista JSON. Para isso, utilizamos o seguinte código:

var temperatura = respo.body.list[0].main.temp -271;

var dataDia = resp.body.list[0].dt_txt;

Note que para a temperatura é subtraída 271 unidades uma vez que a mesma está em Kelvin. O próximo passo agora é inserir no banco de dados a informação extraída mas…

Normal se sentir assim depois de tanta informação.

Ok, você deve estar cansado agora, realmente é muita informação para absorver. Tome um tempo, descanse um pouco, volte para o texto depois. Quando comecei o texto, não imaginei que seria tanto conteúdo. Bom, vamos continuar?

Agora, vamos nos preocupar com o nosso banco de dados, começaremos com o arquivo modelo que é um objeto que representa os dados armazenados, por exemplo:

Nesse simples arquivo temos o objeto “tempSchema” que é um “mongoose.Schema”, nele iremos guardar duas informações: temperatura e a data dessa temperatura. De grosso modo, para banco de dados sql convencionais, isso seria as informações da nossa nova tabela.

Beleza, continuando com o arquivo route.js teremos o seguinte:

db.insertUser(temperatura,dataDia,function(newTemp){...})

Isso é uma chamada de função do objeto db que foi extraído do módulo de biblioteca,querys.js uma biblioteca que foi desenvolvida por nós, logo mais entraremos nela. Observe os parâmetros passados para o método “insertUser” do objeto: temperatura, a data extraida, e uma outra função que será o nosso callback, vamos entrar em mais detalhes sobre esses callbacks quando abordarmos a requisição get do nosso servidor uma vez que a explicação será mais lúcida. Note que essa função passada recebe como parâmetro o valor inserido e responde para o cliente um JSON com o dado recebido.

Querys.js

Nesse arquivo estão os nossos dois métodos que interagem com nosso banco de dados Mongo através da biblioteca Mongoose. Observe a biblioteca importada, ela é o nosso objeto que criamos no nosso Model.js, lembra? Trabalhar com objetos Schema do mongoose deixa a inserção de informação muito mais fácil e intuitiva.

Primeiramente, veja os argumentos recebidos como parâmetro (lembra que enviamos elas no nosso arquivo route.js?) inclusive nossa função callback que será executada no final do método.

As três primeiras linhas são bastante simples, você cria o objeto temp, e da valor para os seus dois atributos, temperatura e data dia de acordo com os parâmetros recebidos na chamada da função.

Por último, salvamos o objeto no banco de dados chamando um método do nosso objeto Schema newTemp.save(function(err){...}) . Que recebe uma função como parâmetro que é executada em seguida, se a inserção apresentar algum erro (banco de dados offline por exemplo) ele irá me enviar imprimir o erro no console. Caso dê tudo certo, ele irá chamar a função callback, que foi passada por parâmetro, com ela é possível que ele execute instruções somente quando toda a função de inserção no banco tenha sido executada, impedindo assim erros causados pela assincronicidade da tecnologia node. Vamos aprofundar mais sobre esse assunto mais para frente.

Agora que validamos nosso método POST, vamos para o nosso método GET, está acabando! Vamos agora pegar o último dado inserido e mostrar em uma página HTML. Vamos voltar para o nosso arquivo route.js, na função de get:

Essa função é bastante simples ainda mais considerando as explicações dadas anteriormente, basicamente, é chamado a nossa comunicação com o banco, ao invés de inserir dados no banco, é extraído o primeiro valor do banco (cheque querys.js para ver como funciona, é bastante simples). Após extrair os dados, é limpado um pouco a quantidade de decimais com o comando substring(0,5) . Por fim é renderizado uma página html com o framework ejs, um framework que facilita a comunicação entre o back-end e o front-end. Iremos abordar isso mais a frente, primeiramente, vamos entender melhor sobre callback.

Christoph Waltz interpretando perfeitamente um Event-Loop esperando ansiosamente pelo seu callback.

Callbacks

Para compreender melhor, o que é um callback, vamos mudar um pouco nosso código. Ao invés de enviarmos uma função para ser executada, vamos armazenar a informação em uma variável que irá pegar o return da função chamada.

Se executarmos a função, o correto seria imprimir o valor que foi pego do nosso banco de dados mongoDB correto? Porém, ao imprimir o resultado, o valor será undefined ! Isso ocorre por causa da assincronicidade da chamada de callbacks do node.js que é realmente o poder do node js. Toda vez que uma função é chamada, ela é executada em paralelo em uma outra thread, e as instruções abaixo serão executados sem ao menos esperar o retono da nossa chamada. O callback é justamente para contornar esse problema, é criado uma função e mandado junto para que seja executada após as instruções do método. Dessa forma você garante sincronicidade no seu código. Bem legal não? Existem diversos outros métodos para garantir isso, como awaits e promisses.

Disponibilizando dados para o usuário.

Por fim, vamos mandar uma página html simples para o usuário para que ele consiga ver de forma clara a temperatura do dia.

O foco desse artigo é não abordar muito a parte de front-end. Acho válido, porém, mostrar uma ferramenta muito simples e eficiente para nós, desenvolvedores back-end, disponibilizar informações para o usuário através de uma página web. O framework ejs (semelhante ao jade) é extremamente útil para trabalhar para enviar dados e receber dados do servidor. Nele é possível trabalhar com variáveis dentro do html. Veja na seção:

<h1><%=info[0].temperatura%><h1>

Dessa forma será disponibilizado a temperatura para todos dentro da marcação h1.

A variável foi passada dentro de uma função na res.render() acima. Muito simples!

Finalmente acabamos! O código está no meu github para acesso. :)

Uma foto minha na apresentação Google Developer’s Group para lembrá-los de nunca esquecer o event-loop!

E agora?

Depois de quase três mil palavras digitadas, ainda falta muita coisa para explicar sobre a tecnlogia node.js. Não vimos nada sobre autenticação de sessão e outros processos importantes em uma API. Deixem nos comentários assuntos que desejam discutir sobre.

Não sei se esse formato com muito conteúdo irá dar certo na plataforma Medium, mas sempre quis fazer um tutorial iniciante de node afim de ajudar entusiastas da área. Qualquer feedback é muito importante para mim!

Mais uma vez, queria agradecer a Nerdzão por divulgar o conteúdo!

Keep on hacking!

--

--