Skip to main content

Node JS



Introdução ao Node.js


O Node.js é um ambiente usado para a execução de código JavaScript (runtime), que é interpretado pelo V8 Engine durante a execução do programa. Essa engine (motor) é escrita em C++, com isso, escrevemos um código Java Script (mas não é 100% Java Script, existem algumas boas diferenças) que será convertido para C++ graças ao V8 Engine. Isso possibilita uma alta performance na execução do código.


O Node.js fornece um console interativo que você pode acessar digitando node no terminal ou prompt de comando sem a necessidade de usar um arquivo com os códigos, o Python também possui um console desses. Aqui no NodeJS esse console se chama REPL (Read-Eval-Print Loop).

Para sair do console interativo, basta teclar Ctrl+c duas vezes ou apenas Ctrl+d.



NPM


O npm é um gerenciador de pacotes para o Node.js, assim como o pip é o gerenciador de pacotes para Python. Com ele nós poderemos baixar novas bibliotecas que serão usadas no nosso código. Também podemos fazer a execução de determinados scripts do programa que estivermos criando.


Os módulos ou bibliotecas baixadas pelo npm ficam num diretório chamado node_modules, esse diretório deve ser descartável, a cada instalação do projeto, o npm baixa todos os pacotes novamente.


Além de instalar um pacote localmente (dentro de um projeto), também podemos instalar um pacote globalmente usando o NPM, assim ele não precisa estar dentro de um projeto específico. Podemos usar o seguinte comando:

npm install -g <nome_do_pacote>

O parâmetro -g indica que você deseja instalar o pacote globalmente, ou seja, disponível em todo o sistema, não apenas em um projeto específico. Isso é útil para pacotes que você deseja acessar de qualquer lugar no seu sistema, como ferramentas de linha de comando.



NPM vs YARN


O NPM (Node Package Manager) e o Yarn são gerenciadores de pacotes para o ecossistema Node.js. Ambos são usados para instalar, compartilhar e gerenciar as dependências do projeto. O Yarn foi criado para ser uma alternativa mais rápida e confiável ao NPM. Ele foi desenvolvido pelo Facebook, Google, Exponent e Tilde.


O Yarn oferece melhor desempenho em termos de velocidade de instalação e resolve problemas de segurança e consistência com mais eficiência do que o NPM. No entanto, o NPM também é bastante popular e tem sido amplamente utilizado na comunidade Node.js.



Criando um projeto com NPM


É possível instalar pacotes usando o NPM mesmo sem iniciar um projeto. No entanto, a maioria das ferramentas e bibliotecas disponíveis através do NPM são projetadas para serem usadas em um contexto de projeto Node.js. Esses pacotes podem exigir configurações específicas, arquivos de configuração ou estruturas de diretório que são mais adequadas para projetos Node.js.


Iniciar um projeto Node.js com o comando npm init cria um arquivo package.json, que é usado para gerenciar as dependências e metadados do projeto. Isso permite que você instale e gerencie pacotes específicos para o seu projeto, além de fornecer informações úteis sobre o projeto e suas dependências.


Se você está trabalhando em um projeto Node.js e precisa de pacotes adicionais, é recomendável iniciar um projeto com npm init e, em seguida, instalar os pacotes necessários usando o NPM. Isso ajudará a organizar e gerenciar suas dependências de forma mais eficiente e evitar conflitos entre diferentes projetos.


Criando um projeto com NPM

# Crie um diretório para o projeto e entre no diretório:
mkdir p001 && cd p001

# Inicie o Projeto:
npm init

Gerenciando pacotes com NPM

Para gerenciar pacotes com o NPM, você pode usar os seguintes comandos:

ComandoDescrição
npm install nome_do_pacoteInstala um pacote no seu projeto.
npm install nome_do_pacote --saveInstala um pacote e o adiciona como uma dependência no arquivo package.json.
npm install nome_do_pacote --save-devInstala um pacote como uma dependência de desenvolvimento no arquivo package.json.
npm uninstall nome_do_pacoteRemove um pacote do seu projeto.
npm update nome_do_pacoteAtualiza um pacote para a versão mais recente.
npm listLista todas as dependências do projeto.
npm updateAtualiza os pacotes instalados do projeto.
npm update packagenameAtualiza um pacotes específico do projeto.
npx npm-check-updates -uVerifica se existem algum pacote do projeto que precisa ser atualizado, nesse caso, ignora as versões dos pacotes em package.json. Depois de rodar ele, basta executar npm install nomedopacote.
npm run scriptÉ usado para executar scripts definidos no arquivo package.json de um projeto Node.js.
npm link nomedopacoteCopia os arquivos de um módulo instalado globalmente para o projeto local, fazendo com que o projeto consiga acessar os arquivos do módulo.
NPM com Script

Veja como está meu package.json:

{
"name": "p001",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

Agora adicione:

package.json
{
"name": "p001",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Sem teste configurado\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

Agora teste:

$ npm run test

> p001@1.0.0 test
> echo "Sem teste configurado" && exit 1

Sem teste configurado


Instalando o Node.js e NPM no Linux


A instalação via repositório no Ubuntu é bastante simples:

sudo apt install -y nodejs npm

No Ubuntu 23.10, a versão atual do repositório nesse momento é:

  • NodeJS: 18.13.0
  • NPM: 9.2.0

Podemos ver a versão do NodeJS e do NPM usando os comandos abaixo:

# Veja a versão do NodeJS instalado:
$ nodejs -v
v18.13.0

# Veja a versão do NPM instalado:
$ npm -v
9.2.0



Exibindo mensagens no console de execução


O console.log("") é uma expressão que chama o método log do objeto console em JavaScript. O console.log é utilizado para exibir mensagens no console do ambiente de execução, como o console de um navegador web ou o console do Node.js.


hello_world.js
console.log("Olá, Mundo!");

Agora é só executar:

$ nodejs hello_world.js
Olá, Mundo!

Ainda podemos configurar o arquivo para ser executável e rodar o nodejs:

hello_world.js
#!/usr/bin/nodejs

console.log("Olá, Mundo!");

Agora vamos dar permissão de execução para o arquivo:

# Dê permissão de execução:
$ chmod +x hello_world.js

# Agora execute em forma de script:
$ ./hello_world.js
Olá, Mundo!


Strings


Uma string é uma sequência de caracteres, ou seja, uma coleção ordenada de caracteres que pode incluir letras, números, espaços, pontuações e outros caracteres especiais. Em muitas linguagens de programação, incluindo JavaScript (e, por extensão, Node.js), as strings são usadas para representar e manipular texto.


Uma variável declarada fora de uma função ou bloco aninhado, será reconhecida dentro de todas as funções ou blocos aninhados do código. Entende-se que variáveis criadas fora de funções ou blocos aninhados são do escopo Global. Variáveis declarada dentro de uma função, só serão reconhecidas dentro da função em que foram declaradas, os blocos aninhados dentro de uma função herdarão as variáveis declaradas na função.


No JavaScript (e NodeJS), existem algumas palavras-chave que são usadas na criação de variáveis, essas palavras-chaves são:

  • let - Cria uma variável mutáveis (o valor dela poderá ser modificado mais para frente). Não pode ser chamada antes de ser declarada.

  • const - Cria uma variável imutável (o valor dela não poderá ser modificado mais para frente). Não pode ser chamada antes de ser declarada. Pode ser visto como constantes, que tem o mesmo significado de imutável.

  • var - Pode ser chamada antes de ser declarada, mas o valor undefined será exibido.


Comentários no código podem ser realizados usando a opção // para linha única e para multi linhas, comece com /* e termine com */, semelhante ao HTML. Em JavaScript podemos declarar valores com o uso de aspas ou apóstrofos para variáveis que recebem valores de string (números não precisa). No momento de usar o valor da variável o interpretador consegue diferenciar uma string literal de uma variável durante a execução do código, isso é conhecido como avaliação dinâmica.


let variavel_peso = 95;

let person = {
nome: 'Bob',
idade: 30,
peso: variavel_peso
};

console.log(person.peso);


console.log(person);

Resultado do código acima

$ node index.js 95 { nome: 'Bob', idade: 30, peso: 95 }


O código acima representa muito bem que o interpretador consegue identificar que variavel_peso em peso: variavel_peso é uma variável e não uma string literal. Porém, caso você queira substituir o valor da chave pelo valor de uma variável, é necessário usar colchetes []:

let kg = 'peso';
let variavel_peso = 95;

let person = {
nome: 'Bob',
idade: 30,
[kg]: variavel_peso
};

console.log(person);

Resultado do código acima

$ node index.js { nome: 'Bob', idade: 30, peso: 95 }



Concatenar strings


No Node.js (e em JavaScript em geral), podemos usar alguns operadores para concatenar strings.


Usando o operador + para junção de strings:

let a = 'Abe';
let b = 'lha';

console.log(a + b);

Resultado do código acima

$ node index.js Abelha


No JavaScript, o operador * não é usado para repetir uma string como em Python. Para alcançar esse efeito, podemos usar repeat(N), onde N é a quantidade de vezes:

let a = 'Abe';

console.log(a.repeat(3));

Resultado do código acima

$ node index.js AbeAbeAbe


O operador , pode ser usado para unir strings com espaços (semelhante ao Python):

let a = 'Abe';
let b = 'lha';

console.log(a, b);

Neste caso, o operador , adiciona um espaço entre as duas strings ao imprimi-las.


Resultado do código acima

$ node index.js Abe lha



Template Literals


Template literals são strings que permitem a interpolação de expressões, incluindo variáveis e até mesmo expressões aritméticas, dentro de strings. Para criar template literals devemos usar o caractere conhecido como crase.

let variavel_peso = 95;

nome = 'Bob'
idade = 30
peso = variavel_peso

console.log(`O ${nome} tem ${idade} anos de idade e pesa ${peso} Kg.`);

Resultado do código acima

$ node index.js O Bob tem 30 anos de idade e pesa 95 Kg.



Interpolar Strings


Também podemos usar %s para indicar que o valor deve ser substituído pela variável que vem logo em seguida:

const nome = "Alice";

console.log("Olá, %s!", nome);

Resultado do código acima

$ node index.js Olá, Alice!


Podemos usar com mais de uma variável também:

const nome = "Alice";
const sobrenome = 'Fernanda';

console.log("Olá, %s!. Seu sobrenome %s é muito bonito", nome, sobrenome);

Resultado do código acima

$ node index.js

Olá, Alice!. Seu sobrenome Fernanda é muito bonito



Argumentos com process.argv


O módulo process função argv fornece uma maneira de passar argumentos ao programa NodeJS.


A estrutura de process.argv é a seguinte:

  • process.argv[0]: Caminho para o executável Node.js.
  • process.argv[1]: Caminho para o script Node.js que está sendo executado.
  • process.argv[2] e além: Argumentos fornecidos na linha de comando.

Exemplo simples usando process.argv:

index.js
// slice(2) = Pega tudo depois do segundo índice (descartando os índices 0 e 1):
const args = process.argv.slice(2)
console.log(args);

const nome = args[0].split('=')[1]
console.log(nome);

// args[0] = Primeiro índice de 'args'
// split('=')[1] = Divide quando ver o símbolo de igual e pega a primeira parte (começa em zero).

Agora no terminal execute:

nodejs index.js arg1=valor arg2
[ 'arg1=valor', 'arg2' ]
valor

Outro método é pegar os argumentos pelos seus respectivos números ou usar o slice.

index.js
const nodejs_path = process.argv[0]
console.log(nodejs_path);

const indexjs_path = process.argv[1]
console.log(indexjs_path);

const arg1 = process.argv[2]
console.log(arg1);

const arg2 = process.argv[3]
console.log(arg2);

Resultado do código acima

$ nodejs index.js arg1=valor arg2

/usr/bin/node /tmp/index.js arg1=valor arg2



Módulos


No Node.js, os módulos são arquivos JavaScript que podem ser importados e usados em outros arquivos JavaScript. Eles fornecem uma maneira de organizar seu código em unidades modulares e reutilizáveis.


Existem três tipos principais de módulos no Node.js:

  • Core Modules: São módulos integrados ao Node.js e podem ser usados sem instalação adicional. Alguns exemplos de módulos principais incluem fs, http e path.
  • Extern Modules: São módulos criados por outras pessoas e podem ser instalados usando o gerenciador de pacotes npm. Você pode encontrar uma variedade de módulos de terceiros no site npmjs.com.
  • Our Modules: São os módulos que nós mesmos criamos.

Para importar um módulo em seu código, você pode usar a palavra-chave require ou import. É importante notar que por questões de boas práticas, a variável que vai receber o módulo terá o mesmo nome do módulo que está sendo importado.

// Importando com 'require':
const fs = require('fs');

// Importando com 'import':
import fs from 'fs';

O conceito de "importar um módulo para dentro de uma variável" geralmente está relacionado à atribuição do conteúdo do módulo a uma variável específica. Isso é feito para que você possa acessar e utilizar as funcionalidades ou dados fornecidos pelo módulo de uma maneira mais conveniente.



Our Modules


Quando se cria módulos em Node.js, geralmente é uma prática comum exportar funcionalidades ou objetos para que possam ser usados em outros arquivos ou módulos. Exportar permite que você torne partes específicas do seu código acessíveis a outros módulos ou arquivos, promovendo uma abordagem modular e reutilizável.


Para exportar podemos usar a instrução module.exports ou a abreviação exports. Essencialmente, você está tornando disponíveis determinadas variáveis, funções ou objetos para outros módulos que precisam delas.


Método 1 de exportar:

mymodule.js
function sum(a, b) {
console.log(a + b);
}

// Exportando a função
module.exports = sum;

Método 2 de exportar:

mymodule.js
module.exports = {
sum(a, b) {
console.log(a + b);
}
}

Como a função está diretamente em module.exports não precisamos colocar a palavra function.


Agora vamos criar o script que vai usar o módulo criado:

index.js
/* Precisa fornecer o caminho de onde está o módulo, no caso está no mesmo diretório.
Não precisa colocar o '.js'. */
const mym = require('./mymodule');
const soma = mym.sum

// Usando a função importada
soma(6, 2)

Esse método de importar um módulo segue as práticas comuns e convenções estabelecidas, visando à clareza, organização e facilidade de leitura do código.


Resultado do código acima

$ nodejs index.js 8



Import e Export do ES6


ES6, ou ECMAScript 2015, é a sexta edição do padrão ECMAScript, que é a especificação na qual o JavaScript é baseado. Lançada em 2015, a ES6 introduziu várias novas funcionalidades e melhorias à linguagem JavaScript. Isso significa que são funcionalidades mais modernas e com mais recursos do que as opções anteriores.


Para podermos usar os novos métodos, precisamos modificar os nossos arquivos para a extensão .mjs.


Novo método de exportar módulos:

mymodule.mjs
function sum(a, b) {
console.log(a + b);
}

export default sum;

Novo método de importar módulos:

index.mjs
import soma from './mymodule.mjs';

soma(2, 9)

Resultado do código acima
11


Módulos Externos


O comando npm init é utilizado para inicializar um novo projeto Node.js. Ao executar este comando no terminal, o npm guiará você por uma série de perguntas interativas para configurar as informações básicas do seu projeto, como nome, versão, descrição, ponto de entrada (entry point), scripts e outras configurações.


O comando npm init também gera um arquivo chamado package.json. Esse é um arquivo de configuração fundamental que contém informações sobre o projeto, dependências, scripts de execução, versão, autor, etc.


Sempre que for iniciar um novo projeto, deve-se executar npm init, após isso os módulos ficam mapeados e podem ser instalados. É nesse ponto em que os módulos são salvos no diretório nodes_modules.


# Crie um diretório para iniciar o projeto e entre nele:
$ mkdir nodep1 && cd nodep1

# Agora inicialize o projeto (por hora as opções default vão servir):
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (nodep1)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/bsilva/nodep1/package.json:

{
"name": "nodep1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}


Is this OK? (yes) yes


minimist


O minimist é um módulo Node.js que facilita o parsing (análise) de argumentos da linha de comando. Ele é útil quando você precisa extrair valores específicos de uma lista de argumentos passados na linha de comando ao executar um script. A principal funcionalidade do minimist é converter os argumentos da linha de comando em um objeto JavaScript, tornando mais fácil acessar e utilizar esses valores.


Primeiro, instale o minimist usando o npm:

$ npm install minimist

added 1 package, and audited 2 packages in 481ms

1 package is looking for funding
run `npm fund` for details

found 0 vulnerabilities

Crie um arquivo para js para testar:

index.js
const minimist = require('minimist');

// Obtendo os argumentos da linha de comando
const args = minimist(process.argv.slice(2));

// Extraindo valores específicos
const nome = args.nome || 'Usuário';
const idade = args.idade || 25;

console.log(`Olá, ${nome}! Você tem ${idade} anos.`);

Agora execute o script com argumentos da linha de comando:


Resultado do código acima

$ node index.js --nome=Bob --idade=30 Olá, Bob! Você tem 30 anos.


Como nós usamos || na declaração das variáveis nome e idade, caso não seja fornecido nada, será usado os valores que fornecemos como valores padrões:

Resultado do código acima

$ node index.js Olá, Usuário! Você tem 25 anos.



inquirer


O inquirer é um módulo que simplifica a criação de interfaces de linha de comando interativas, especialmente quando se trata de fazer perguntas ao usuário e coletar suas respostas. Ele oferece uma variedade de tipos de perguntas predefinidos, como listas, caixas de seleção, perguntas abertas, entre outros.


Para usar o inquirer, temos que instalar ele:

npm install inquirer@8.1.2

A versão mais recente possui algumas diferenças na importação, podendo gerar alguns erros.


Veja um exemplo básico de como usar o inquirer:

index.js
const inquirer = require('inquirer');

// Definindo as perguntas
const perguntas = [
{
type: 'input',
name: 'nome',
message: 'Qual é o seu nome?'
},
{
type: 'list',
name: 'fruta',
message: 'Escolha uma fruta:',
choices: ['Maçã', 'Banana', 'Morango', 'Uva']
}
];

// Perguntando ao usuário
inquirer.prompt(perguntas)

// O que será executado de fato:
.then((answers) => {
console.log('Respostas:', answers);
})

// Sempre que der erro ele vai para o 'catch', usamos ele para exibir o erro:
.catch((error) => {
console.error('Erro:', error);
});

Resultado do código acima

$ node index.js

? Qual é o seu nome? fulano ? Escolha uma fruta: Banana Respostas: { nome: 'fulano', fruta: 'Banana' }


O inquirer.prompt é usado para apresentar as perguntas definidas no array perguntas. As respostas do usuário são capturadas no método .then().


O inquirer fornece diversos tipos de perguntas (tipo 'input', 'list', 'checkbox', etc.), permitindo que você colete informações de maneira flexível. Além disso, você pode personalizar as perguntas de acordo com as necessidades do seu aplicativo.


As variáveis dentro de .then e .catch é onde o inquirer vai armazenar as respostas.


Em JavaScript, as Promises (Promessas) são objetos que representam o resultado de uma operação assíncrona, que pode ser resolvida (com sucesso) ou rejeitada (com falha). As promessas permitem que você trabalhe com código assíncrono de uma maneira mais limpa e eficiente, evitando assim o aninhamento excessivo de callbacks (conhecido como callback hell).


Uma promessa pode estar em um de três estados:

  1. Pendente (Pending): O estado inicial de uma promessa. Isso significa que a operação assíncrona ainda não foi concluída.
  2. Resolvida (Fulfilled): A operação assíncrona foi concluída com sucesso.
  3. Rejeitada (Rejected): A operação assíncrona falhou.

As promessas têm dois métodos principais que você pode usar para interagir com elas:

  1. then(): Este método é usado para lidar com o caso em que a promessa é resolvida com sucesso. Ele recebe duas funções de retorno de chamada como argumentos, uma para o caso de sucesso e outra para o caso de falha.
  2. catch(): Este método é usado para lidar com o caso em que a promessa é rejeitada. Ele recebe uma função de retorno de chamada que será chamada se a promessa for rejeitada.

Neste exemplo:

  • Criamos uma nova promessa que simula uma operação assíncrona.
  • Dentro da promessa, usamos resolve() para indicar sucesso e reject() para indicar falha.
  • Usamos then() para lidar com o caso de sucesso e catch() para lidar com o caso de falha.


Módulos Built-in


O Node vem com diversos módulos built-in prontos para serem utilizados. Vejamos alguns módulos Built-In do Node que acabei documentando.



Módulo FS


O módulo fs (File System) é um módulo integrado no Node.js que fornece funcionalidades relacionadas ao sistema de arquivos. Com o fs, você pode realizar várias operações de leitura, escrita e manipulação de arquivos e diretórios no sistema de arquivos local.




fs.readFile


Lêr o conteúdo de um arquivo.

const fs = require('fs');

// fs.readFile(): Lê o conteúdo de um arquivo.
fs.readFile('arquivo.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});


fs.writeFile


Escrever num arquivo.

const fs = require('fs');

// fs.writeFile(): Escreve dados em um arquivo, substituindo o conteúdo existente.
fs.writeFile('arquivo.txt', 'Novo conteúdo', 'utf8', (err) => {
if (err) {
console.error(err);
return;
}
console.log('Arquivo escrito com sucesso!');
});


fs.readdir


Lê o conteúdo de num diretório, semelhante ao ls do Linux.

const fs = require('fs');

// fs.readdir(): Lista os arquivos em um diretório.
fs.readdir('.', (err, files) => {
if (err) {
console.error(err);
return;
}
console.log('Arquivos no diretório:', files);
});


fs.mkdir


Cria um diretório, semelhante ao mkdir do Linux.

const fs = require('fs');

// fs.mkdir(): Cria um novo diretório.
fs.mkdir('novo_diretorio', (err) => {
if (err) {
console.error(err);
return;
}
console.log('Diretório criado com sucesso!');
});


fs.rmdir


Remove um diretório, semelhante ao rmdir do Linux.

const fs = require('fs');

// fs.rmdir()`: Remove um diretório.
fs.rmdir('diretorio_para_remover', (err) => {
if (err) {
console.error(err);
return;
}
console.log('Diretório removido com sucesso!');
});


PATH


O módulo path é um módulo integrado do Node.js que fornece utilitários para trabalhar com caminhos de arquivos e diretórios. Ele é particularmente útil para lidar com caminhos de forma segura e independente do sistema operacional, garantindo que seu código seja portátil e funcione em diferentes plataformas.



path.extname


Retorna a extensão de um arquivo.

index.js
const path = require('path');
const caminhofile = path.extname("arquivo.txt");

// Resultado depende do sistema operacional: /pasta/subpasta/arquivo.txt ou \pasta\subpasta\arquivo.txt
console.log(caminhofile)

Resultado do código acima

$ node index.js .txt



readline


O módulo readline é utilizado para realizar operações de leitura de entrada do usuário a partir de streams (como o terminal). Ele fornece uma interface para ler dados de uma stream linha por linha, o que é útil para criar interfaces de linha de comando interativas.


Além disso, o método question é uma parte do módulo readline que permite fazer perguntas interativas ao usuário, esperar por uma resposta e executar uma função de retorno de chamada com a resposta fornecida pelo usuário.

Aqui está um exemplo básico de como usar readline e readline.question:

index.js
// Importa o módulo já executando ele:
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});

// Pergunta ao usuário
readline.question('Qual é o seu nome? ', (resposta) => {
console.log(`Olá, ${resposta}!`);

// Fecha a interface de leitura
readline.close();
});

readline.createInterface é usado para criar uma interface de leitura a partir das streams de entrada (process.stdin) e saída (process.stdout).


readline.question é utilizado para fazer uma pergunta ao usuário, e a função de retorno de chamada é acionada quando o usuário fornece uma resposta. O método readline.close() é chamado para encerrar a interface de leitura depois que a pergunta é respondida.


resposta é o nome da variável onde vamos armazenar a resposta do usuário (qualquer coisa que ele digitar).



EventEmitter


O EventEmitter é uma classe no módulo events que fornece uma implementação de um padrão de design chamado "Emitter/Observer" ou "Publish/Subscribe". Esse padrão permite que objetos emitam e escutem eventos nomeados, facilitando a comunicação e coordenação entre partes distintas de um aplicativo.


A classe EventEmitter é usada para criar objetos que podem emitir (disparar) eventos e registrar ouvintes (listeners) para esses eventos. Um objeto que herda de EventEmitter pode ser usado como um canal de comunicação entre diferentes partes do código.


Aqui está um exemplo básico de como usar EventEmitter:

index.js
const EventEmitter = require('events');

// Criando um objeto EventEmitter
const evenEmitter = new EventEmitter();

// Registrando um ouvinte para o evento 'eventoPersonalizado'
evenEmitter.on('start', () => {
console.log('durante');
});

console.log('Antes');

// Emitindo o evento 'start' com alguns dados:
evenEmitter.emit('start');

console.log('depois');

Resultado do código acima

$ node index.js Antes
durante
depois



HTTP


O módulo http é usado para criar servidores HTTP e interagir com protocolos HTTP. Com este módulo, você pode construir aplicativos web, criar APIs e lidar com solicitações e respostas HTTP.

index.js
const http = require('http');

const port = 8080

const server = http.createServer((req, res) => {
res.write('Hellow World!');
res.end(); // encerra a conexão para nao ficar aberto para sempre!
});

server.listen(port, () => {
console.log(`Servidor rodando em http://localhost:${port}/`);
});

O método createServer cria o servidor web, ele recebe uma função de retorno de chamada que é chamada sempre que uma solicitação é recebida. Esta função de retorno de chamada recebe dois argumentos: req (requisição) e res (resposta).


Resultado do código acima

$ node index.js Servidor rodando em http://localhost:${port}/


http://localhost:8080

Hellow World!



Retornar um HTML no HTTP


index.js
const http = require('http');

const port = 8080

const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/html');
res.end('<h1>Olá, este é apenas um teste!!!');
});

server.listen(port, () => {
console.log(`Servidor rodando em http://localhost:${port}/`);
});


URL


O módulo url é um módulo que fornece utilitários para manipulação e análise de URLs. Ele é útil para extrair informações específicas de URLs, como partes do caminho, parâmetros de consulta, hostname, etc.


index.js
const url = require('url');

const url_address = 'https://www.meusite.com.br/catalog?produtos=cadeira';

const parsedUrl = url.parse(url_address, true); // O segundo argumento 'true' faz com que os parâmetros de consulta sejam convertidos em um objeto

console.log('Protocolo:', parsedUrl.protocol);
console.log('Host:', parsedUrl.host);
console.log('Hostname:', parsedUrl.hostname);
console.log('Porta:', parsedUrl.port);
console.log('Caminho:', parsedUrl.pathname);
console.log('Parâmetros de Consulta:', parsedUrl.query);

Resultado do código acima

$ node index.js Protocolo: https: Host: www.meusite.com.br Hostname: www.meusite.com.br Porta: null Caminho: /catalog Parâmetros de Consulta: [Object: null prototype] { produtos: 'cadeira' }



Função


Uma função é um bloco de código que realiza uma tarefa específica. Ela pode ser chamada de qualquer lugar do seu código, desde que você chame ela após declara-lá, o que facilita a organização e o reuso de código.


Criando uma função simples:

// Cria a função chamada minhaFuncao:
function minhaFuncao() {
console.log("Olá, mundo!");
}

// Chamando a função
minhaFuncao();

Nós também podemos passar argumentos para uma função. Os argumentos são valores que a função pode usar para realizar uma tarefa.

// Cria a função soma, nela definimos duas variáveis: A e B:
function soma(a, b) {
// Retorna a soma de a e b
return a + b;
}

// Chamando a função informando o valor de A (a=2) e B (b=3):
let resultado = soma(2, 3);

console.log(resultado); // Imprime 5


Função Estática


Uma função estática é uma função associada a uma classe ou a um objeto que pode ser chamada sem criar uma instância desse objeto. No contexto de classes, uma função estática é definida usando a palavra-chave static. Isso significa que a função está associada à classe em si, e não a instâncias individuais da classe.


Isso permite que você chame a função diretamente na classe, sem precisar criar um objeto dessa classe. Aqui está um exemplo de como uma função estática pode ser definida em uma classe em Node.js:

class MyClass {
static staticFunction() {
console.log('Esta é uma função estática!');
}
}

// Chama a função estática diretamente na classe, sem criar uma instância
MyClass.staticFunction();

Resultado do código acima

$ node index.js Esta é uma função estática!

No exemplo acima, staticFunction é uma função estática da classe MyClass, e pode ser chamada diretamente na classe sem instanciá-la.


Uma função estática em uma classe é útil para operações que não dependem de uma instância específica da classe, mas ainda são úteis para a classe como um todo. Você pode chamá-las diretamente na classe, sem precisar criar um objeto daquela classe.



Estruturas de condições


Estruturas de condição permitem que um programa execute diferentes blocos de código com base em uma condição lógica. Essas estruturas permitem tomar decisões e direcionar o fluxo do programa com base em diferentes cenários.


No JavaScript, você usará os operadores de comparação da seguinte forma:

  • <: Menor que
  • >: Maior que
  • <=: Menor ou igual a
  • >=: Maior ou igual a
  • ==: Igual a (verifica apenas o valor, não o tipo)
  • ===: Estritamente igual a (verifica o valor e o tipo)
  • !=: Diferente de (verifica apenas o valor, não o tipo)
  • !==: Estritamente diferente de (verifica o valor e o tipo)

Note que o operador de atribuição = é usado apenas para atribuir valores a variáveis.



IF


A estrutura if permite que um bloco de código seja executado se uma condição específica for verdadeira.

#################################
# Estrutura #
#################################

if (condition) {
// Código a ser executado se a condição for verdadeira
} else if (condition) {
// Código a ser executado se a condição for verdadeira
} else {
// Código a ser executado se a condição for falsa
}

Exemplo geral do uso com IF:

const objeto = { chave1: 'valor1', chave2: 'valor2' };

if ('chave1' in objeto) {
console.log('A chave1 existe no objeto.');
} else {
console.log('A chave1 não existe no objeto.');
}


Switch


A estrutura switch é usada para avaliar uma expressão em relação a vários casos possíveis.

switch (expressao) {
case valor1:
// Bloco de código a ser executado se expressao for igual a valor1
break;

case valor2:
// Bloco de código a ser executado se expressao for igual a valor2
break;

default:
// Bloco de código a ser executado se nenhum caso corresponder
}


Estruturas de repetição


As estruturas de repetição permitem a execução repetida de um bloco de código com base em determinadas condições ou contadores. Essas estruturas são valiosas para automatizar tarefas repetitivas e melhorar a eficiência dos programas.



For


O loop for é especialmente útil quando você sabe antecipadamente quantas vezes deseja que o código seja repetido. Ele geralmente possui três partes principais: uma inicialização, uma condição de continuação e uma expressão de iteração.

#################################
# Estrutura #
#################################

for (<initialization>; <continuation condition>; <iterable>) {
<statement(s)>
}

Exemplo geral do uso com For:

// Imprime os números pares de 0 a 10 usando um loop for

for (let i = 0; i <= 10; i++) {
if (i % 2 === 0) {
console.log(i);
}
}

O que faz i % 2?

A expressão i % 2 calcula o resto da divisão de i por 2. Esse operador é chamado de operador de módulo. O resultado dessa expressão será zero se i for um número par e será 1 se i for um número ímpar.



While


O loop while é uma estrutura de repetição mais flexível, pois continua executando o bloco de código enquanto uma condição especificada for verdadeira.

#################################
# Estrutura #
#################################

while (<condition>) {
<statement(s)>
}

Exemplo geral do uso com While:

let contador = 0;

while (contador < 5) {
console.log(`Iteração ${contador + 1}`);
contador++;
}

// Resultado:
// Iteração 1
// Iteração 2
// Iteração 3
// Iteração 4
// Iteração 5


Objetos


Os objetos em JavaScript são coleções de pares chave-valor, onde as chaves são strings ou símbolos e os valores podem ser de qualquer tipo de dado, incluindo outros objetos. No Python é conhecido como Dicionários.

// Criando um Objeto simples e vazio:
let empty_object = {};

// Criando um Objeto simples e vazio:
let person = {
nome: 'Bob',
idade: 30,
peso: 95
};

Podemos também criar objetos aninhados. Objetos aninhados são basicamente uma chave um valor, mas o valor acaba recebendo outro conjunto de chaves e valores, é uma prática comum para organizar e estruturar dados de maneira hierárquica. Segue um exemplo simples:

let pessoa = {
nome: 'João',
idade: 25,
endereco: {
rua: 'Rua Principal',
cidade: 'Cidade A',
estado: 'Estado X'
}
};

// Acessando propriedades do objeto aninhado
console.log(pessoa.nome);
console.log(pessoa.endereco.cidade);

console.log(pessoa);

Resultado do código acima

$ node index.js João Cidade A depois { nome: 'João', idade: 25, endereco: { rua: 'Rua Principal', cidade: 'Cidade A', estado: 'Estado X' } }



Arrays


Os Arrays funcionam como coleções ordenadas de elementos do mesmo tipo, armazenados em uma sequência contígua de memória. Imagine um array como uma fila onde cada item ocupa uma posição específica. Os Arrays são conhecidos como listas no Python e Array em Shell Script 😅.

O Array sempre começa em 0.


// Criando um Array:
const array1 = [1, 2, 3, 4]
const array2 = ['laranja', 'mamão', 'maçã', 'uva']


// A variável `segundaFruta` recebe o segundo elemento de array2 (índice 1)
const segundaFruta = array2[1];
console.log(segundaFruta);

// Percorrendo o array usando for loop
for (let i = 0; i < array2.length; i++) {
console.log(array2[i]);
}

Resultado do código acima

$ node index.js mamão laranja mamão maçã uva



push()


O método push é usado para adicionar um ou mais elementos ao final de um array.

const array = ["a", "b", "c"];

array.push("d"); // Adiciona "d" ao final do array

console.log(array);

Resultado do código acima

$ node index.js ["a", "b", "c", "d"]



spread ...


O operador spread ... em JavaScript é utilizado para copiar elementos de um array (ou objetos) para outro array (ou objeto) de forma rápida e concisa. Ele também pode ser utilizado para espalhar elementos em uma função ou em uma expressão.

const array = ["a", "b", "c"];
const newArray = [...array, "d"];

console.log(newArray);

Resultado do código acima

$ node index.js ["a", "b", "c", "d"]



concat


O método concat em JavaScript é utilizado para combinar dois ou mais arrays, criando um novo array que contém todos os elementos dos arrays originais. Ele não modifica os arrays originais, mas retorna um novo array contendo os elementos concatenados.

const array = ["a", "b", "c"];
const newArray = array.concat(["d"]);

console.log(newArray);

Resultado do código acima

$ node index.js ["a", "b", "c", "d"]



pop()


O método pop() em JavaScript é utilizado para remover o último elemento de um array e retornar esse elemento. Ele modifica o array original, reduzindo seu comprimento em 1.

const array = ["a", "b", "c"];

const removedValue = array.pop(); // Remove "c" do final do array

console.log(array);
console.log(removedValue);

Resultado do código acima

$ node index.js ["a", "b"] "c"



splice()


O método splice() em JavaScript é utilizado para modificar o conteúdo de um array, adicionando ou removendo elementos. Ele permite realizar operações mais complexas do que os métodos push() e pop(), pois você pode adicionar, remover e substituir elementos em posições específicas do array.


A sintaxe geral do método splice() é a seguinte:

array.splice(inicio, quantidadeRemovida, elemento1, elemento2, ...);
  • inicio: Índice no array onde a modificação começará.
  • quantidadeRemovida: Número de elementos a serem removidos a partir do índice de início. Se for 0, nenhum elemento é removido.
  • elemento1, elemento2, ...: Elementos a serem adicionados no array a partir do índice de início.

Adicionar elementos em uma posição específica:

let meuArray = [1, 2, 3, 4, 5];
meuArray.splice(2, 0, 6, 7);

console.log(meuArray); // Resultado: [1, 2, 6, 7, 3, 4, 5]

Neste exemplo, a partir do índice 2, nenhum elemento é removido (0), e os elementos 6 e 7 são adicionados no array.


Remover elementos em uma posição específica:

let meuArray = [1, 2, 3, 4, 5];
meuArray.splice(2, 2);

console.log(meuArray); // Resultado: [1, 2, 5]

Neste exemplo, a partir do índice 2, dois elementos são removidos, resultando no array [1, 2, 5].


Substituir elementos em uma posição específica:

let meuArray = [1, 2, 3, 4, 5];
meuArray.splice(2, 2, 6, 7);

console.log(meuArray); // Resultado: [1, 2, 6, 7, 5]

Neste exemplo, a partir do índice 2, dois elementos são removidos, e os elementos 6 e 7 são adicionados no lugar, resultando no array [1, 2, 6, 7, 5].



filter()


O método filter() em JavaScript é utilizado para criar um novo array contendo apenas os elementos do array original que atendem a uma condição específica. Ele não modifica o array original, mas retorna um novo array contendo os elementos filtrados.


const array = ["a", "b", "c", "d"];

const newArray = array.filter(element => element !== "b"); // Adiciona os elementos que são diferente "b" do array

console.log(newArray); // ["a", "c", "d"]

A expressão element => element !== "b" é uma função de seta que verifica se cada elemento do array original (array) é diferente de b. Se o elemento não for igual a b, ele é incluído no novo array (newArray). Se for igual a b, é excluído do novo array.



indexOf()


O método indexOf é utilizado para encontrar a posição de uma determinada substring em uma string. Ele retorna o índice da primeira ocorrência da substring na string, ou -1 se a substring não for encontrada.

const array = ["a", "b", "c", "d"];

const position = array.indexOf("c"); // Retorna a posição de "c" no array

console.log(position);

Resultado do código acima

$ node index.js 2



findIndex()


O método findIndex é uma função de array em JavaScript, e não uma função diretamente relacionada a strings como o indexOf. No entanto, é possível utilizá-lo para encontrar o índice de um elemento em um array que satisfaça uma determinada condição.

const array = ["a", "b", "c", "d"];

const position = array.findIndex(element => element === "c"); // Retorna a posição de "c" no array

console.log(position);

Resultado do código acima

$ node index.js 2



chalk


O chalk é uma biblioteca popular em Node.js usada para colorir a saída no console. Com ela, você pode adicionar cores, estilos e fundos ao texto que é exibido no terminal. Isso é particularmente útil ao criar interfaces de linha de comando (CLI) ou ao destacar mensagens importantes.


Para utilizar o chalk, precisamos instalá-lo primeiro, para isso vamos usar o npm:

# Instalando o chalk localmente:
npm install chalk

added 1 package in 207ms

1 package is looking for funding
run `npm fund` for details

Para desinstalar a versão do Chalk, podemos usar: npm uninstall chalk.


Aqui está um exemplo simples de como usar o chalk:

const chalk = require('chalk');

// Exemplo de uso
console.log(chalk.blue('Este é um texto azul'));
console.log(chalk.red.bold('Este é um texto vermelho e em negrito'));
console.log(chalk.bgGreen.white('Este texto tem fundo verde e cor branca'));

// Com template literals
const mensagem = chalk.yellow`Esta mensagem está em amarelo`;
console.log(mensagem);

O código acima usa diversas funções do chalk para colorir e estilizar o texto. Algumas das funções comumente utilizadas incluem chalk.bold, chalk.italic, chalk.underline, e várias funções de cor, como chalk.red, chalk.blue, chalk.green, entre outras.

O chalk fornece uma maneira fácil de adicionar estilo ao seu output no console, tornando a leitura e interpretação das mensagens mais visuais e informativas.



Módulos com Argumentos


Vou criar um script que vai usar um módulo e fornecer argumentos via scripts passando para o módulo executar uma soma.

soma.js
module.exports = {
soma(a,b) {
console.log(a + b);
}
}

index.js
const minimist = require('minimist');

// o '.soma' estamos pegando a função 'soma' de dentro do módulo 'soma' (./soma)
const soma = require('./soma').soma

// Obtendo os argumentos da linha de comando
const args = minimist(process.argv.slice(2));

// parseInt é uma função usada para analisar uma string e retornar um número inteiro:
const a = parseInt(args['a']);
const b = parseInt(args['b']);

soma(a, b)

Agora vamos executar:

$ node index.js --a=2 --b=98
100


Console


O objeto console é uma parte integrante do ambiente JavaScript, comumente utilizado em ambientes como navegadores (dentro do console do desenvolvedor) e no ambiente Node.js. Ele fornece métodos para a exibição de mensagens no console do desenvolvedor ou na saída padrão do terminal, dependendo do ambiente de execução.


Abaixo podemos ver alguns dos métodos mais comuns disponíveis no objeto console.



Console.log


Imprime mensagens no console.

console.log("Olá, mundo!");


Console.info


Funciona de maneira semelhante ao console.log, mas geralmente é usado para mensagens informativas.

console.info("Isso é uma informação.");


Console.warn


Exibe uma mensagem de advertência.

console.warn("Isso é uma advertência!");


Console.error


Exibe uma mensagem de erro.

console.error("Algo deu errado!");


Console.table


Exibe dados tabulares na forma de uma tabela.

const dados = [
{ nome: 'Alice', idade: 25 },
{ nome: 'Bob', idade: 30 }
];

console.table(dados);

Resultado do código acima

$ node index.js ┌─────────┬─────────┬───────┐ │ (index) │ nome │ idade │ ├─────────┼─────────┼───────┤ │ 0 │ 'Alice' │ 25 │ │ 1 │ 'Bob' │ 30 │ └─────────┴─────────┴───────┘



Console.clear


Limpa o console.

console.clear();


Console.group


Agrupa mensagens no console.

console.group("Grupo A");
console.log("Mensagem 1");
console.log("Mensagem 2");
console.groupEnd();

console.group("Grupo B");
console.log("Mensagem 3");
console.log("Mensagem 4");
console.groupEnd();

Resultado do código acima

$ node index.js Grupo A Mensagem 1 Mensagem 2 Grupo B Mensagem 3 Mensagem 4



Console.assert


Exibe uma mensagem de erro se a expressão fornecida for falsa.

console.assert(2 + 2 === 5, "Erro: 2 + 2 não é igual a 5");

Resultado do código acima

$ node index.js Assertion failed: Erro: 2 + 2 não é igual a 5



Console.count


O console.count é usado para contar quantas vezes o método foi chamado. Ele é útil para rastrear a frequência de execução de um trecho de código específico.


A sintaxe básica do console.count é a seguinte:

console.count([rótulo]);

  • rótulo (opcional): Uma string que serve como identificador para o contador. Se fornecido, o contador será incrementado apenas se o rótulo for o mesmo nas chamadas subsequentes.

Exemplo:

function exemplo() {
console.count("Chamada da Função");
console.log("Executando a função...");
}

exemplo();
exemplo();
exemplo();

Resultado do código acima

$ node index.js Chamada da Função: 1 Executando a função... Chamada da Função: 2 Executando a função... Chamada da Função: 3 Executando a função...



Lidando com erros


O try, catch, e throw são construções usadas para lidar com exceções e erros.



try


O bloco try é usado para envolver um trecho de código no qual você espera que ocorram erros. O código dentro do bloco try é executado normalmente. Se uma exceção ocorrer durante a execução deste bloco, o controle é transferido para o bloco catch.

try {
// Código que pode gerar uma exceção
} catch (error) {
// Bloco executado se ocorrer uma exceção
}


catch


O bloco catch é onde você trata a exceção capturada no bloco try. O parâmetro error (ou qualquer nome que você escolher) contém informações sobre a exceção que ocorreu.

try {
// Código que pode gerar uma exceção
} catch (error) {
// Bloco executado se ocorrer uma exceção
console.error('Ocorreu um erro:', error);
}


throw


A palavra-chave throw é usada para lançar uma exceção manualmente. Você pode usá-la para sinalizar que algo inesperado ocorreu em seu código.

index.js
const x = "10"

if (!Number.isInteget(x)) {
throw new Error("O valor não é inteiro.")
}

console.log('Continuando o código');

Resultado do código acima

$ node index.js 95 { nome: 'Bob', idade: 30, peso: 95 }



HTTP com URL


Vejamos um exemplo muito simples e básico.


index.js
const http = require('http');

const port = 8080

const server = http.createServer((req, res) => {
const urlinfo = require('url').parse(req.url, true)
const name = urlinfo.query.name

res.statusCode = 200
res.setHeader('Content-Type', 'text/html');

if(!name) {
res.end('<h1>Coloque seu nome!</h1><form method="GET"><input type="text" name="name" /><input type="submit" value="Enviar" /></form>');

} else {
res.end(`<h1>Olá, seja bem vindo ${name} </h1>`);

}

});

server.listen(port, () => {
console.log(`Servidor rodando em http://localhost:${port}/`);
});


Renderizando HTML com FS


index.js
const http = require('http');
const fs = require('fs');

const port = 8080

const server = http.createServer((req, res) => {
fs.readFile('mensagem.html', function(err, data) {

res.writeHead(200, {'Content-Type': 'text/html'})
res.write(data)
return res.end()
})
})

server.listen(port, () => {
console.log(`Servidor rodando em http://localhost:${port}/`);
})

mensagem.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mensagem</title>
</head>
<body>
<h1>Este arquivo foi lido pelo fs!</h1>
</body>
</html>

LinhaCódigoDescrição
1const http = require('http');Importa o módulo http do Node.js, que fornece funcionalidades para criar servidores HTTP.
2const fs = require('fs');Importa o módulo fs (file system) do Node.js, que fornece funcionalidades para manipular arquivos.
4const port = 8080Define a variável port com o valor 8080, indicando a porta em que o servidor irá escutar.
6-16const server = http.createServer((req, res) => { ... })Cria um servidor HTTP usando o método createServer. A função de retorno de chamada é executada quando uma solicitação é recebida.
8-15fs.readFile('mensagem.html', function(err, data) { ... })Lê o conteúdo do arquivo mensagem.html de forma assíncrona. A função de retorno de chamada é executada quando a leitura é concluída.
10res.writeHead(200, {'Content-Type': 'text/html'})Configura o cabeçalho da resposta com o código de status 200 (OK) e o tipo de conteúdo como text/html.
11res.write(data)Escreve o conteúdo do arquivo lido na resposta.
12return res.end()Finaliza a resposta, indicando que nenhum outro conteúdo será enviado.
18-20server.listen(port, () => { ... })Inicia o servidor para escutar na porta especificada (8080) e exibe uma mensagem quando estiver pronto para receber solicitações.

A função dentro de fs.readFile é uma função de retorno de chamada (callback). No Node.js, muitas operações, como a leitura de arquivos, são assíncronas. Isso significa que o código não espera pela conclusão da operação e continua executando outras tarefas enquanto a operação assíncrona está em andamento.


A função de retorno de chamada é uma maneira de lidar com o resultado de uma operação assíncrona quando ela é concluída. Nesse caso específico, a função de retorno de chamada é acionada quando a leitura do arquivo mensagem.html é concluída.


  • err: É o objeto de erro. Se a operação for bem-sucedida, err será null. Se houver um erro, err conterá informações sobre o erro.

  • data: Contém os dados lidos do arquivo. Se não houver erros, data conterá o conteúdo do arquivo.



Escrevendo em arquivos


Vamos usar um formulário HTML para escrever num arquivo.

index.js"
const http = require("http");
const fs = require("fs");
const url = require("url");

const port = 8080;

const server = http.createServer((req, res) => {
var urlInfo = require("url").parse(req.url, true);
const name = urlInfo.query.name;

res.statusCode = 200;
res.setHeader("Content-Type", "text/html");

if (!name) {
fs.readFile("index.html", function (err, data) {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(data);
return res.end();
});
} else {
fs.writeFile("arquivo.txt", name, function (err, data) {
res.writeHead(302, {
Location: "/",
});
return res.end();
});
}
});

server.listen(port, () => {
console.log(`Servidor rodando na porta: ${port}`);
});

A linha de código var urlInfo = require("url").parse(req.url, true); utiliza o módulo url para analisar a URL contida no objeto de solicitação (req).


  • .parse(req.url, true): O método parse do módulo url é chamado para analisar a URL contida em req.url.

    • req.url: Contém a parte da URL após o domínio, incluindo o caminho e os parâmetros de consulta.

    • true: O segundo argumento (true) especifica que os parâmetros de consulta devem ser convertidos em um objeto. Se for false ou omitido, os parâmetros de consulta serão retornados como uma string.


A linha de código const name = urlInfo.query.name; está extraindo o valor do parâmetro de consulta chamado "name" do objeto urlInfo.


  • urlInfo.query: A propriedade query do objeto urlInfo contém um objeto com os parâmetros de consulta da URL. O segundo argumento true indica que os parâmetros de consulta devem ser convertidos em um objeto.

  • urlInfo.query.name: Aqui, name é uma propriedade específica que está sendo acessada no objeto urlInfo.query. Se a URL da solicitação incluir um parâmetro de consulta chamado "name", então urlInfo.query.name conterá o valor associado a esse parâmetro.

  • const name = ...;: O valor obtido é atribuído à constante name. Agora, a variável name contém o valor do parâmetro de consulta "name" da URL.


index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mensagem</title>
</head>
<body>
<h1>Como você se chama?</h1>
<form action="/" method="GET">
<input type="text" name="name" placeholder="Insira seu nome" />
<input type="submit" value="Enviar" />
</form>
</body>
</html>


Criando um sistema de contas


# Crie o projeto:
mkdir p002 && cd p002 && npm init -y

# Instale os pacotes abaixo:
npm install inquirer@8.1.2 chalk@4.1.2

Adicione a sessão abaixo no seu package.json (sessão em destaque):

package.json
{
"name": "p002",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}

Crie index.js com o conteúdo abaixo:

index.js
// modulos externos:
const inquirer = require("inquirer");
const chalk = require("chalk");

// modulos internos:
const fs = require("fs");

console.log('Iniciando o sistema de contas!')

process.setMaxListeners(0)

function operationsonaccounts () {

inquirer.prompt([{
type: 'list',
name: 'action',
message: 'O que você deseja fazer? ',
choices: [
'Criar conta',
'Deletar uma conta',
'Consultar saldo',
'Depositar',
'Sacar',
'Sair'],
},
])
.then((answer) => {
const action = answer['action']

if (action === 'Criar conta') {
createAccount()
} else if (action === 'Depositar') {
Depositar()
} else if (action === 'Deletar uma conta') {
delconta()
} else if (action === 'Consultar saldo') {
getAccountBalance()
} else if (action === 'Sacar') {
pegarmoney()
} else if (action === 'Sair') {
console.log(chalk.bgBlue.black('Obrigado por usar o Accounts!'))
process.exit()
}

})
.catch((err) => console.log(err))
}


// create user account
function createAccount() {
console.log(chalk.bgGreen.black('Obrigado por escolher nosso sistema!'))
console.log(chalk.green('Escolha uma das opções a seguir'))

criarconta()
}

// Função para criar a conta:
function criarconta() {
inquirer
.prompt([
{
name: 'accountName',
message: 'Digite o nome da sua conta:',
},
])
.then((answer) => {
console.info(answer['accountName'])

const accountName = answer['accountName']

// Verifica se o diretório 'accounts' existe!
if (!fs.existsSync('accounts')) {
// Se não existir, cria!
fs.mkdirSync('accounts')
}

// Verifica se o nomedaconta.json existe:
if (fs.existsSync(`accounts/${accountName}.json`)) {
console.clear();
console.log(
chalk.bgRed.black('Esta conta já existe, escolha outro nome!'),
)
// Se existir, pede para escolher outro nome
criarconta(accountName)
return
} else {
// Se não existir, cria o json com o nome da conta
fs.writeFileSync(
`accounts/${accountName}.json`,
'{"balance":0}',
function (err) {
console.log(err)
},
)

console.log(chalk.green('Parabéns, sua conta foi criada!'))
// Agora volta do início:
operationsonaccounts()
}
})
}

function delconta() {

// Verifica se o diretório 'accounts' existe!
if (!fs.existsSync('accounts')) {
// Se não existir, cria!
console.clear();
console.log(chalk.bgRed.black("Nenhuma conta no sistema!"))
operationsonaccounts()
} else {

inquirer
.prompt([
{
name: 'accountName',
message: 'Digite o nome da conta para deletar:',
},
])
.then((answer) => {
console.info(answer['accountName'])
const accountName = answer['accountName']

// Verifica se o nomedaconta.json existe:
if (!checkAccount(accountName)) {
// retorna novamente para a função, para digitar o nome novamente.
return delconta()
}

fs.unlink(`accounts/${accountName}.json`, (err) => {
if (err) {
console.error(err);
return;
} else if (!fs.existsSync(`accounts/${accountName}.json`)) {
console.clear();
console.log(chalk.bgRed.black('Conta removida com sucesso!'));

// Agora volta do início:
operationsonaccounts()
}
});
})
}
}

function getAccount(accountName) {
// Lê o arquivo:
const accountJSON = fs.readFileSync(`accounts/${accountName}.json`, {
encoding: 'utf8', // já lê usando utf8
flag: 'r', // Somente 'ler (read)' o arquivo
})

return JSON.parse(accountJSON) // retorna o arquivo em json
}

// add an amount to user account
function Depositar() {
inquirer
.prompt([
{
name: 'accountName',
message: 'Qual o nome da sua conta?',
},
])
.then((answer) => {
const accountName = answer['accountName']

// Se 'checkAccount' retornar false, execute o IF:
if (!checkAccount(accountName)) {
// retorna novamente para a função, para digitar o nome novamente.
return Depositar()
}

inquirer
.prompt([
{
name: 'amount',
message: 'Quanto você deseja depositar?',
},
])
.then((answer) => {
const amount = answer['amount']

if (!verificarvalor(amount)) {
Depositar();
return // precisa do return ja que é um erro no sistema, sem ele quebra tudo!!
}

// Chama a função que faz o depósito:
addAmount(accountName, amount)

// Volta para o inicio:
operationsonaccounts()
})
})
}


function addAmount(accountName, amount) {
const accountData = getAccount(accountName) // accountData recebe o o json pela função 'getAccount'

console.log('Object.balance', accountData.balance)

if (!amount) {
console.log(
chalk.bgRed.black('Ocorreu um erro, tente novamente mais tarde!'),
)
return Depositar()
}

// .balance é a chave 'balance' que está no json 'accountData', nesse caso, retorna o valor
// da chave 'balance', que é o valor que tem na conta!!
accountData.balance = parseFloat(amount) + parseFloat(accountData.balance) // Soma o valor a ser depositado com o valor atual da conta!

fs.writeFileSync(
`accounts/${accountName}.json`,
JSON.stringify(accountData), // transforma o json em texto, informando o json = accountData
function (err) {
console.log(err)
},
)

console.log(
chalk.green(`Foi depositado o valor de R$${amount} na sua conta!`),
)
}


function checkAccount(accountName) {
if (!fs.existsSync(`accounts/${accountName}.json`)) {
console.log(chalk.bgRed.black('Esta conta não existe, escolha outro nome!'))
return false
}
return true
}

function getAccountBalance() {
inquirer
.prompt([
{
name: 'accountName',
message: 'Qual o nome da sua conta?',
},
])
.then((answer) => {
const accountName = answer['accountName']

if (!checkAccount(accountName)) {
return getAccountBalance()
}

const accountData = getAccount(accountName)

console.log(
chalk.bgBlue.black(
`Olá, o saldo da sua conta é de R$${accountData.balance}`,
),
)
operationsonaccounts()
})
}


function verificarvalor(isdigit) {

//console.log(isdigit)

if (!isNaN(isdigit)) { // Verifica se o valor é um número
return true;
} else {
console.log("Valor indefinido, favor digitar um número para o depósito!");
return false;
}
}


// get money from account
function pegarmoney() {
inquirer
.prompt([
{
name: 'accountName',
message: 'Qual o nome da sua conta?',
},
])
.then((answer) => {
const accountName = answer['accountName']

if (!checkAccount(accountName)) {
return pegarmoney()
}

inquirer
.prompt([
{
name: 'amount',
message: 'Quanto você deseja sacar?',
},
])
.then((answer) => {
const amount = answer['amount']

removeAmount(accountName, amount)
operationsonaccounts()
})
})
}

function removeAmount(accountName, amount) {
const accountData = getAccount(accountName) // accountData recebe o json pela função 'getAccount'

if (!amount) {
console.log(
chalk.bgRed.black('Ocorreu um erro, tente novamente mais tarde!'),
)
return pegarmoney()
}

if (accountData.balance < amount) {
console.log(chalk.bgRed.black('Valor indisponível!'))
return pegarmoney()
}

// .balance é a chave 'balance' que está no json 'accountData', nesse caso, retorna o valor
// da chave 'balance', que é o valor que tem na conta!!
accountData.balance = parseFloat(accountData.balance) - parseFloat(amount)

fs.writeFileSync(
`accounts/${accountName}.json`,
JSON.stringify(accountData),
function (err) {
console.log(err)
},
)

console.log(
chalk.green(`Foi realizado um saque de R$${amount} da sua conta!\nAgora você possui apenas RS${accountData.balance} na conta.`),
)
}

operationsonaccounts()