Servidores e bancos de dados com Node.js

Servidores e bancos de dados com Node.js

No artigo anterior falamos sobre desenvolvimento web e como funcionam as páginas que utilizam a arquitetura cliente-servidor. A partir deste artigo começaremos a investigar a parte Backend, focada na criação do servidor e no gerenciamento do banco de dados.

Para a criação deste servidor utilizaremos o Node.js e posteriormente implementaremos o MongoDB como banco de dados.

Mas antes de começarmos com o projeto, onde iremos criar um servidor profissional, gostaria de apresentar a vocês vários conceitos do Node.js. Recomendo que visite o link a seguir que o levará a um artigo de um colega onde ele apresenta o Node.js em termos de desempenho, facilidades, entre outros.

¿Cómo executar JavaScript fuera del navegador?

Como sabemos, podemos escrever código JavaScript em um navegador apenas acessando o console, mas graças ao Node podemos executar JavaScript sem a necessidade de um navegador.

A seguir, para mostrar como fazer, usarei o Visual Studio Code, um IDE (Integrated Development Environment) muito utilizado para desenvolvimento em JavaScript e é o que usaremos no restante do curso. Aqui você pode baixar o VScode.

Vamos seguir estes passos:

1) Vamos ao VScode e abrimos seu terminal com command + j (Mac) o Ctrl + Shift + ` (PC), poderíamos usar qualquer terminal, mas para evitar trocar de janela muitas vezes, usaremos o VScode integrado.

2) Entramos no nó de comando, que nos abrirá node REPL (Read Eval Print Loop), uma ferramenta de linha de comando que captura a entrada do código JavaScript, interpreta-a e avalia a saída do código.

3) Se pressionarmos Tab duas vezes, aparecerá uma lista de funcionalidades válidas para usar no nodo REPL. Para sair disso, inserimos o comando .exit.

Módulos no Node

Para nos aprofundarmos nos tópicos do Node, vamos agora nos apresentar aos módulos. Um módulo no Node é apenas um arquivo JavaScript que contém o código relacionado. Em JavaScript, usamos as palavras-chave import e export para compartilhar e receber funcionalidades, respectivamente, em diferentes módulos. A palavra-chave export é usada para tornar uma variável, função, classe ou objeto acessível a outros módulos.

Temos 3 tipos de módulos: Core Modules, Local Modules e Third Party Modules.

1- Core modules

Os Core Modules ou módulos principais incluem funcionalidades mínimas do Node.js. Eles são compilados em sua distribuição binária e carregados automaticamente quando o processo Node.js é iniciado. No entanto, o módulo deve primeiro ser importado para o arquivo onde queremos implementá-lo para usá-lo em nosso aplicativo.

Alguns dos módulos mais importantes

http -> Incluye clases, métodos y eventos para crear un servidor http en Node.js.

url -> Inclui métodos para análise e resolução de URL.

querystring -> Incluye métodos para tratar con la cadena de consulta (query string).

path -> Inclui métodos para lidar com a string de consulta.

fs -> Inclui classes, métodos e eventos para trabalhar com arquivos de Input/Output.

util -> Inclui funções utilitárias úteis para programadores.

2- Local modules

Módulos locais são aqueles criados localmente em seu aplicativo Node.js. Esses módulos incluem diferentes funcionalidades do seu aplicativo em arquivos e pastas separados. Você também pode empacotá-lo e distribuí-lo via NPM, para que a comunidade Node.js possa usá-lo. Por exemplo, se você precisar se conectar ao MongoDB e obter dados, poderá criar um módulo para ele que possa ser reutilizado em seu aplicativo.

3- Third Party Modules

São módulos disponíveis online e são instalados via npm. Eles também são chamados de módulos de terceiros. Alguns exemplos de módulos de terceiros são Express, Mongoose, etc.

Core modules e seus usos

Nesta parte, usarei os conceitos mencionados acima para criar vários casos de uso para os módulos principais. Estes mesmos formarão grande parte do nosso dia a dia como desenvolvedores Backend.

Aqui abordaremos um exemplo de leitura e gravação de arquivos como estão, o que também pode explicar a natureza assíncrona do Node.js. No entanto, este não será o único artigo onde você encontrará exemplos práticos de módulos principais, então... Fique atento aos meus próximos artigos!

A leitura e escrita de arquivos, como o próprio nome indica, é responsável por obter o conteúdo de um arquivo de texto, bem como criá-lo e escrevê-lo.


Escrita síncrona

// Precisamos o core module 'fs', nos permite 
// ler e escrever arquivos
const fs = require('fs');

// Salvamos na variável um texto que queremos salvar
let texto = 'Este é apénas um texto de amostra';

// Finalmente, usamos o módulo fs para criar o arquivo e salvar
// o texto criado antes
// este arquivo vai ser criado com o método 'writeFileSync'
// que vai ser salvado no diretório onde o arquivo vai ser salvado 
// e depois damos-lhe o texto que queremos 
// salvar neste
fs.writeFileSync('./escritura.txt', texto);

Para executar este arquivo devemos ter noções básicas de manipulação de comandos no terminal. Se você não tem, não se preocupe, eu vou te orientar para que você saiba como fazer no futuro.

Por enquanto faça os seguintes passos:

- Abra este arquivo no VScode.
- Uma vez no VScode. abra o terminal com Ctrl + J se estiver usando o Windows ou Command + J se estiver usando no Mac.
- Passe o comando "node " (obviamente sem aspas e com o nome do arquivo onde você salvou o código).

E pronto! Instantaneamente, o arquivo de texto será criado com o que você salvou.

Leitura síncrona

// Precisamos o módulo 'fs' para ler um arquivo
const fs = require('fs');

// Criamos depois uma variável onde vamos salvar o que ganhamos com 
// a leitura de um arquivo de texto usando o método 
// "readFileSync", que devemos passar ao
//diretório do arquivo que queremos ler e depois
// passamos 'utf-8', a codificação do caracteres mais comum da 
//World Wide Web.
const texto = fs.readFileSync('./escritura.txt', 'utf-8');

// Finalmente, poderiamos usar esta variável para fazer o que queremos 
// com o que ganhamos, mas neste casso só vamos a mostrar por 
// console
console.log(texto);

Quando executarmos este código (como fizemos com o anterior), obteremos o que está salvo no arquivo de texto no console.

Isso funciona muito bem, embora tenha um problema: tudo o que fizemos foi feito de forma síncrona, o que nos leva ao próximo tópico.

Código de bloqueio y no bloqueo, a natureza assíncrona do Node.js

Quando falamos em código síncrono, entendemos que esse código é executado linha por linha, ou seja, até que uma ação termine de ser executada, não será possível passar para outra. Como você pode pensar, isso causará um enorme problema de bloqueio de código, o que tornaria o código lento. Para resolver esse problema, o código assíncrono é usado.

Para explicar melhor, vamos ver algumas imagens explicativas do case:

O Node.js executa seus aplicativos em um encadeamento único (single thread) onde todos os usuários se conectarão. Portanto, é importante não bloqueá-lo.

Se usarmos código síncrono, bloquearemos esse thread e o aplicativo ficará desnecessariamente lento.

Se usarmos código assíncrono, enviaremos as tarefas que bloqueiam nosso código para um segundo plano onde terminarão a execução e, uma vez resolvidas, o resultado será retornado ao thread principal.

Para obter esse código assíncrono, usamos as funções de retorno de chamada. Embora isso resolva o problema, não significa que os callbacks sejam códigos assíncronos ou a melhor solução, pois existem mais alternativas como promessas e funções async/await, conceitos que revisaremos mais adiante.

Lendo e gravando arquivos de forma assíncrona

Escrita assíncrona

// Precisamos o módulo 'fs'
const fs = require('fs');

// O mesmo módulo permite usar métodos assíncronos, neste caso
// 'writeFile' pega os mesmos parâmetros que 'writeFileSync', mas 
// a diferencia é que passamos um callback 
// function
fs.writeFile('./escrituraAsync.txt', `algo que queramos guardar`, err => {
    console.log("O seu arquivo foi criado!");
});

Leitura assíncrona

const fs = require('fs');

// Este método pega os mesmos parâmetros que o 'readFileSync', mas como
// terceiro parâmetro pega uma callback function, cujos parâmetros são 
// primeiro onde vai ficar o erro se algo der errado, e como 
// segundo parâmetro o que foi obtido em essa leitura
fs.readFile('./escritaAsync.txt', 'utf-8', (err,data) => {
    console.log(data);
})

Leitura e escrita assíncrona

const fs = require('fs');

// Primeiro lemos um arquivo e salvamos o seu conteúdo na callback 
// function
fs.readFile('./escrituraAsync.txt', 'utf-8', (err,data1) => {
    // Depois fazemos uma escrita em um arquivo usando o que foi salvado 
    // antes para salvarlo novamente em outro arquivo, e 
    // também adicionando uns detalhes mais
    fs.writeFile('./final.txt', `${data1}\\nE pronto!`, err => {
        console.log("O seu arquivo foi criado corretamente!");
    });
});

Dessa forma, a gravação e a leitura de arquivos podem ser usadas para uma ampla variedade de atividades.

Aqui deixarei o repositório do GitHub onde você encontrará todos os códigos usados ​​neste artigo e em artigos futuros.

E isso e tudo ! Em meu próximo post, usarei alguns módulos principais para criar um servidor simples e roteado, além de muito mais.

Cumprimentos!

⚠️
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.