Fundamentos de JavaScript, Node.js e Arquitetura Cliente-Servidor
🎯 Objetivo: Compreender os conceitos fundamentais do desenvolvimento backend e dominar JavaScript essencial para Node.js
0% concluído
Arquitetura Cliente-Servidor e Setup do Ambiente
Entenda como funciona a comunicação entre o frontend (cliente) e o backend (servidor) na web!
// Simulação de uma requisição HTTP
// 1. CLIENTE (Frontend) - Navegador
const requisicao = {
metodo: 'GET',
url: 'https://api.exemplo.com/usuarios',
headers: {
'Content-Type': 'application/json'
}
};
console.log('📤 Cliente enviando requisição:');
console.log(requisicao);
// 2. SERVIDOR (Backend) - Node.js
function processarRequisicao(req) {
console.log('📥 Servidor recebeu requisição');
// Processamento no servidor
const usuarios = [
{ id: 1, nome: 'Ana', email: 'ana@email.com' },
{ id: 2, nome: 'João', email: 'joao@email.com' }
];
// 3. RESPOSTA do servidor
const resposta = {
status: 200,
dados: usuarios,
mensagem: 'Usuários encontrados com sucesso'
};
console.log('📤 Servidor enviando resposta:');
console.log(resposta);
return resposta;
}
// Simulando o processo completo
const resultado = processarRequisicao(requisicao);
console.log('✅ Comunicação Cliente-Servidor concluída!');
Cliente faz requisição
Navegador envia pedido para o servidor
Servidor processa
Backend executa lógica e acessa dados
Servidor responde
Dados são enviados de volta ao cliente
Cliente exibe resultado
Interface é atualizada com os dados
Node.js permite executar JavaScript no servidor, e o NPM é o gerenciador de pacotes que nos ajuda a instalar bibliotecas!
// Simulação de comandos NPM e Node.js
// 1. Inicializando um projeto Node.js
console.log('📁 Criando novo projeto...');
const packageJson = {
name: 'meu-projeto-backend',
version: '1.0.0',
description: 'Meu primeiro projeto backend',
main: 'index.js',
scripts: {
start: 'node index.js',
dev: 'nodemon index.js'
},
dependencies: {},
devDependencies: {}
};
console.log('✅ package.json criado:');
console.log(JSON.stringify(packageJson, null, 2));
// 2. Instalando uma biblioteca (simulação)
console.log('\n📦 Instalando lodash...');
const lodash = {
name: 'lodash',
version: '4.17.21',
description: 'Biblioteca de utilitários JavaScript'
};
packageJson.dependencies.lodash = '^4.17.21';
console.log('✅ Lodash instalado com sucesso!');
// 3. Usando a biblioteca instalada
console.log('\n🔧 Usando lodash no código:');
// const _ = require('lodash'); // Em Node.js real
// Simulação de uso do lodash
const numeros = [1, 2, 3, 4, 5];
const dobrados = numeros.map(n => n * 2); // Simulando _.map
console.log('Números originais:', numeros);
console.log('Números dobrados:', dobrados);
console.log('\n🎯 Projeto Node.js configurado!');
# Verificar versão do Node.js
$ node --version
v18.17.0
# Inicializar projeto
$ npm init -y
package.json criado!
# Instalar biblioteca
$ npm install lodash
+ lodash@4.17.21
# Executar arquivo
$ node index.js
Servidor rodando...
Simule a criação de um projeto Node.js com as configurações básicas!
JavaScript Essencial: Funções, Escopo e Callbacks
Funções são blocos de código reutilizáveis. No backend, usamos muito funções para organizar nossa lógica!
// 1. Função tradicional
function saudarUsuario(nome, idade) {
return `Olá ${nome}, você tem ${idade} anos!`;
}
// 2. Arrow function (mais moderna)
const calcularIdade = (anoNascimento) => {
const anoAtual = new Date().getFullYear();
return anoAtual - anoNascimento;
};
// 3. Arrow function simplificada (uma linha)
const dobrarNumero = (num) => num * 2;
// 4. Função que simula uma operação de backend
const processarPedido = (produto, quantidade) => {
console.log('🛒 Processando pedido...');
const precos = {
'notebook': 2500,
'mouse': 50,
'teclado': 150
};
const precoUnitario = precos[produto] || 0;
const total = precoUnitario * quantidade;
return {
produto,
quantidade,
precoUnitario,
total,
status: 'processado'
};
};
// Testando as funções
console.log('=== TESTANDO FUNÇÕES ===');
const mensagem = saudarUsuario('Ana', 25);
console.log(mensagem);
const idade = calcularIdade(1998);
console.log(`Idade calculada: ${idade} anos`);
const numeroDobrando = dobrarNumero(15);
console.log(`15 dobrado = ${numeroDobrando}`);
const pedido = processarPedido('notebook', 2);
console.log('📦 Pedido processado:');
console.log(pedido);
Callbacks são funções passadas como parâmetro para outras funções. Muito usado no backend para operações que demoram!
// 1. Callback simples
function executarOperacao(nome, callback) {
console.log(`🔄 Iniciando operação: ${nome}`);
// Simula uma operação que demora
setTimeout(() => {
const resultado = `Operação ${nome} concluída!`;
callback(resultado); // Chama a função callback
}, 1000);
}
// 2. Simulando operações de backend
function lerArquivo(nomeArquivo, callback) {
console.log(`📁 Lendo arquivo: ${nomeArquivo}`);
setTimeout(() => {
const conteudo = `Conteúdo do arquivo ${nomeArquivo}`;
callback(null, conteudo); // null = sem erro
}, 800);
}
function salvarNoBanco(dados, callback) {
console.log('💾 Salvando no banco de dados...');
setTimeout(() => {
const id = Math.floor(Math.random() * 1000);
callback(null, { id, dados, salvoEm: new Date() });
}, 1200);
}
// 3. Usando callbacks (o famoso "Callback Hell")
console.log('=== DEMONSTRAÇÃO DE CALLBACKS ===');
executarOperacao('Teste', (resultado) => {
console.log('✅', resultado);
});
// Exemplo mais complexo - operações em sequência
lerArquivo('config.json', (erro, conteudo) => {
if (erro) {
console.error('❌ Erro ao ler arquivo:', erro);
return;
}
console.log('📄 Arquivo lido:', conteudo);
// Agora salva no banco
salvarNoBanco(conteudo, (erro, resultado) => {
if (erro) {
console.error('❌ Erro ao salvar:', erro);
return;
}
console.log('💾 Dados salvos:', resultado);
console.log('🎯 Processo completo!');
});
});
console.log('⏳ Aguardando operações assíncronas...');
callback1(() => {
callback2(() => {
callback3(() => {
callback4(() => {
// Código difícil de ler!
});
});
});
});
💡 Solução: Promises e async/await (próxima aula!)
Crie um sistema simples de cadastro de usuários usando funções e callbacks!
Promises e Introdução ao Servidor HTTP
Promises tornam o código assíncrono mais limpo e fácil de entender. Essencial para desenvolvimento backend moderno!
// 1. Criando uma Promise
function lerArquivoPromise(nomeArquivo) {
return new Promise((resolve, reject) => {
console.log(`📁 Lendo arquivo: ${nomeArquivo}`);
setTimeout(() => {
if (nomeArquivo.includes('.txt')) {
const conteudo = `Conteúdo do ${nomeArquivo}`;
resolve(conteudo); // Sucesso
} else {
reject(new Error('Arquivo deve ser .txt')); // Erro
}
}, 1000);
});
}
// 2. Promise para salvar no banco
function salvarNoBancoPromise(dados) {
return new Promise((resolve, reject) => {
console.log('💾 Salvando no banco...');
setTimeout(() => {
const id = Math.floor(Math.random() * 1000);
resolve({
id,
dados,
salvoEm: new Date().toISOString()
});
}, 800);
});
}
// 3. Usando Promises com .then() e .catch()
console.log('=== DEMONSTRAÇÃO DE PROMISES ===');
lerArquivoPromise('config.txt')
.then(conteudo => {
console.log('✅ Arquivo lido:', conteudo);
return salvarNoBancoPromise(conteudo);
})
.then(resultado => {
console.log('💾 Dados salvos:', resultado);
console.log('🎯 Processo completo com Promises!');
})
.catch(erro => {
console.error('❌ Erro:', erro.message);
});
// 4. Promise.all() - executar várias promises em paralelo
const promises = [
lerArquivoPromise('arquivo1.txt'),
lerArquivoPromise('arquivo2.txt'),
lerArquivoPromise('arquivo3.txt')
];
Promise.all(promises)
.then(resultados => {
console.log('📚 Todos os arquivos lidos:');
resultados.forEach((conteudo, index) => {
console.log(` Arquivo ${index + 1}: ${conteudo}`);
});
})
.catch(erro => {
console.error('❌ Erro em algum arquivo:', erro.message);
});
console.log('⏳ Aguardando promises...');
Pending (Pendente)
Promise ainda está executando
Fulfilled (Resolvida)
Operação concluída com sucesso
Rejected (Rejeitada)
Operação falhou com erro
Vamos criar nosso primeiro servidor web usando apenas o módulo HTTP nativo do Node.js!
// Simulação de um servidor HTTP básico
// (Em Node.js real, usaríamos: const http = require('http'))
// 1. Simulando o módulo HTTP
const http = {
createServer: (callback) => {
console.log('🌐 Servidor HTTP criado!');
return {
listen: (porta, callback) => {
console.log(`🚀 Servidor rodando na porta ${porta}`);
if (callback) callback();
}
};
}
};
// 2. Criando o servidor
const servidor = http.createServer((req, res) => {
// Esta função é chamada para cada requisição
console.log(`📥 Requisição recebida: ${req.method} ${req.url}`);
// Simulando diferentes rotas
if (req.url === '/') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('Bem-vindo ao meu servidor!
');
} else if (req.url === '/api/usuarios') {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
const usuarios = [
{ id: 1, nome: 'Ana', email: 'ana@email.com' },
{ id: 2, nome: 'João', email: 'joao@email.com' }
];
res.end(JSON.stringify(usuarios));
} else if (req.url === '/sobre') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('Sobre Nós
Este é meu primeiro servidor!
');
} else {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('404 - Página não encontrada
');
}
});
// 3. Iniciando o servidor
servidor.listen(3000, () => {
console.log('✅ Servidor iniciado com sucesso!');
console.log('🔗 Acesse: http://localhost:3000');
});
// 4. Simulando algumas requisições
console.log('\n=== SIMULANDO REQUISIÇÕES ===');
const simularRequisicao = (method, url) => {
console.log(`\n📤 Simulando: ${method} ${url}`);
const req = { method, url };
const res = {
statusCode: 200,
headers: {},
setHeader: function(key, value) {
this.headers[key] = value;
},
end: function(content) {
console.log(`📥 Resposta: ${this.statusCode}`);
console.log(`📋 Headers:`, this.headers);
console.log(`📄 Conteúdo: ${content}`);
}
};
// Simular o processamento da requisição
if (url === '/') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end('Bem-vindo ao meu servidor!
');
} else if (url === '/api/usuarios') {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
const usuarios = [{ id: 1, nome: 'Ana' }];
res.end(JSON.stringify(usuarios));
} else {
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('404 - Página não encontrada
');
}
};
simularRequisicao('GET', '/');
simularRequisicao('GET', '/api/usuarios');
simularRequisicao('GET', '/pagina-inexistente');
📥 Request (req)
Contém dados da requisição (URL, método, headers)
📤 Response (res)
Usado para enviar resposta ao cliente
🛣️ Rotas
Diferentes URLs que o servidor pode responder
📊 Status Codes
200 (OK), 404 (Not Found), 500 (Error)
Crie uma API simples para gerenciar tarefas usando Promises e simulação de servidor HTTP!
Teste todos os conceitos aprendidos em tempo real!
Entendeu como cliente e servidor se comunicam
Dominou funções, callbacks e promises
Criou seu primeiro servidor HTTP
🚀 Próxima semana: Express.js e APIs REST!