A programação orientada a eventos pode ser esmagadora para iniciantes, o que pode dificultar o início do Node.js. Mas não deixe que isso o desanime; Neste artigo, ensinarei alguns conceitos básicos do Node.js e explicarei por que ele se tornou tão popular.
Introdução
Para começar a usar o Node.js, você deve primeiro entender as diferenças entre o Node.js e os ambientes tradicionais de script do lado do servidor, como PHP, Python ou Ruby.
Programação assíncrona
O Node.js usa uma arquitetura de módulo para simplificar a criação de aplicativos complexos.
As chances são boas de que você esteja familiarizado com programação assíncrona; é, afinal, o “A” em AJAX. Toda função no Node é assíncrona. Portanto, tudo o que normalmente bloquearia o encadeamento é executado em segundo plano usando promessas. Esta é a coisa mais importante a ser lembrada sobre o Node. Por exemplo, se você estiver lendo um arquivo no sistema de arquivos, usará uma função assíncrona. Se você estiver usando certas versões da função Node, você usará retornos de chamada, que foram projetados antes da existência das promessas. A maioria das funções do Node tem equivalentes de promessa agora, então uma boa tarefa é converter as funções de retorno de chamada usadas aqui para seus equivalentes baseados em promessa e comparar a sintaxe.
Você está fazendo tudo!
Com o Node, você tem que fazer muito sozinho. Por exemplo, o módulo HTTP é mínimo e sem opinião. Isso pode ser esmagador para novos usuários, mas a recompensa é um aplicativo da Web de alto desempenho (embora uma grande parte do desempenho do JavaScript seja devido ao mecanismo otimizado do V8). Um script lida com toda a comunicação com os clientes. Isso reduz consideravelmente o número de recursos usados pelo aplicativo. Por exemplo, aqui está o código para um aplicativo Node.js simples:
const i, a, b, c, max; max = 1000000000; var d = Date.now(); for (i = 0; i < max; i++) { a = 1234 + 5678 + i; b = 1234 * 5678 + i; c = 1234 / 2 + i; } console.log(Date.now() - d);
E aqui está o equivalente escrito em PHP:
$a = null; $b = null; $c = null; $i = null; $max = 1000000000; $start = microtime(true); for ($i = 0; $i < $max; $i++) { $a = 1234 + 5678 + $i; $b = 1234 * 5678 + $i; $c = 1234 / 2 + $i; } var_dump(microtime(true) - $start);
Agora vamos olhar para os números de referência. A tabela a seguir lista os tempos de resposta, em milissegundos, para esses dois aplicativos simples:
Número de iterações | Node.js | PHP |
100 | 2,00 | 0,14 |
10.000 | 3,00 | 10,53 |
1.000.000 | 15h00 | 1119,24 |
10.000.000 | 143,00 | 10621,46 |
1.000.000.000 | 11118,00 | 1036272.19 |
Executei os dois aplicativos a partir da linha de comando para que nenhum servidor atrasasse a execução dos aplicativos. Fiz cada teste dez vezes e calculei a média dos resultados. O PHP é notavelmente mais rápido com uma quantidade menor de iterações, mas essa vantagem se dissolve rapidamente à medida que o número de iterações aumenta. Quando tudo estiver dito e feito, o PHP é 93% mais lento que o Node.js!
O Node.js é rápido, mas você precisará aprender algumas coisas para usá-lo corretamente.
Módulos
O Node.js usa uma arquitetura de módulo para simplificar a criação de aplicativos complexos. Módulos são semelhantes a bibliotecas em C ou unidades em Pascal. Cada módulo é privado por padrão, mas pode exportar vários valores (por exemplo, funções) para outros módulos, que podem importá-los. Por exemplo, o http módulo contém funções específicas para HTTP. O Node.js fornece alguns módulos principais prontos para uso para ajudá-lo a acessar arquivos no sistema de arquivos, criar servidores HTTP e TCP/UDP e executar outras funções úteis. Existem dois métodos diferentes de usar módulos, CommonJS (CJS) e Módulos ECMAScript (ESM). CommonJS é mais comumente usado em programas Node legados, onde Módulos ECMAScript são usados em navegadores e programas Node mais modernos.
CommonJS
Incluir um módulo é fácil; basta ligar para o require()
função, assim:
const http = require('http');
o require()
A função retorna a referência ao módulo especificado. No caso deste código, uma referência ao http módulo é armazenado no http
variável.
No código acima, passamos o nome de um módulo para o require()
função. Isso faz com que o Node procure um node_modules pasta no diretório do nosso aplicativo e procure o http módulo nessa pasta. Se o Node não encontrar o node_modules pasta (ou o http módulo dentro dele), ele então examina o cache do módulo global. Você também pode especificar um arquivo real passando um caminho relativo ou absoluto, assim:
const myModule = require('./myModule.js');
Para exportar um valor que pode ser necessário, use o exports
objeto e preencha suas propriedades e métodos com os pedaços de código que você deseja expor. Considere o seguinte módulo como exemplo:
exports.area = function (r) { return Math.PI * r ** 2; }; exports.circumference = function (r) { return 2 * Math.PI * r; };
Este código cria um PI
variável que só pode ser acessada pelo código contido no módulo; não é acessível fora do módulo. Em seguida, duas funções são criadas no exports
objeto. Essas funções são acessíveis fora do módulo porque são definidas no exports
objeto. Como resultado, PI
está completamente protegido contra interferências externas. Portanto, você pode ter certeza de que area()
e circumference()
sempre se comportarão como deveriam (desde que um valor seja fornecido para o r
parâmetro).
Módulos ECMAScript
Para incluir um módulo, você usa o import
palavra-chave:
// file import myModule from "./myModule.js" // Node builtin/package import http from "http"
No navegador, o ESM só pode pesquisar usando caminhos de arquivo relativos, como acima. No entanto, no Node, você pode passar um caminho sem ./
para procurar um pacote NPM ou interno do Node. Outra maneira de importar built-ins e pacotes do Node é usar o node:
prefixo.
No entanto, a abordagem anterior funciona apenas com exportações padrão. Se você estiver usando exportações nomeadas (mais sobre isso posteriormente), você precisará usar uma sintaxe ligeiramente diferente.
import { exportOne, exportTwo } from "./myModule.js"
Para exportar algo, use o export
ou export default
palavra-chave. A exportação é para exportações nomeadas e o padrão de exportação é para exportações padrão. As exportações nomeadas permitem que você exporte coisas diferentes e use apenas uma delas em um módulo diferente usando a sintaxe de importação acima. As exportações padrão facilitam se você estiver exportando apenas uma única coisa.
// Named exports export function exportOne() { ... } export function exportTwo() { ... } // Default exports export default function defaultFunction() { ... }
Para o restante deste tutorial, usaremos o ESM
Âmbito global
Node é um ambiente JavaScript executado no mecanismo JavaScript V8 do Google. Como tal, devemos seguir as melhores práticas que usamos para o desenvolvimento do lado do cliente. Por exemplo, devemos evitar colocar qualquer coisa no escopo global. Isso, porém, nem sempre é possível. O escopo global no Node é GLOBAL
(em oposição a window
no navegador), e você pode facilmente criar uma variável global de função omitindo o var
palavra-chave, assim:
globalVariable = 1; globalFunction = function () { ... };
Mais uma vez, os globais devem ser evitados sempre que possível. Portanto, tenha cuidado e lembre-se de usar var
ao declarar uma variável.
Instalação
Naturalmente, precisamos instalar o Node antes de podermos escrever e executar um aplicativo. A instalação é simples, se você usa Windows ou OS X; o site nodejs.org oferece instaladores para esses sistemas operacionais. Para Linux, use qualquer gerenciador de pacotes. Por exemplo, se você estiver usando uma distribuição que suporte apt, abra seu terminal e digite:
sudo apt-get update sudo apt-get install node
ou:
sudo aptitude update sudo aptitude install node
Node.js está em repositórios sid; você pode precisar adicioná-los à sua lista de fontes:
sudo echo deb https://ftp.us.debian.org/debian/ sid main > /etc/apt/sources.list.d/sid.list
Mas esteja ciente de que a instalação de pacotes sid em sistemas mais antigos pode quebrar seu sistema. Tenha cuidado e remova /etc/apt/sources.list.d/sid.list
depois de concluir a instalação do Node.
Instalando Novos Módulos
O Node.js tem um gerenciador de pacotes, chamado Node Package Manager (NPM). Ele é instalado automaticamente com o Node.js e você usa o NPM para instalar novos módulos. Para instalar um módulo, abra seu terminal/linha de comando, navegue até a pasta desejada e execute o seguinte comando:
npm install module_name
Não importa qual sistema operacional você tenha; o comando acima instalará o módulo que você especificar no lugar de module_name
.
O aplicativo Olá Mundo
Naturalmente, nosso primeiro script Node.js imprimirá o texto 'Hello World!'
para o console. Crie um arquivo chamado olá.jse digite o seguinte código:
console.log('Hello World!');
Agora vamos executar o script. Abra o terminal/linha de comando, navegue até a pasta que contém olá.jse execute o seguinte comando:
node hello.js
Você deveria ver 'Hello World!'
exibido no console.
Servidor HTTP
Vamos passar para um aplicativo mais avançado; não é tão complicado quanto você pensa. Vamos começar com o código a seguir. Leia os comentários e depois a explicação abaixo:
// Include http module. import { createServer } from "http" // Create the server. Function passed as parameter is called on every request made. // request variable holds all request parameters // response variable allows you to do anything with response sent to the client. createServer(function (request, response) { // Attach listener on end event. // This event is called when client sent all data and is waiting for response. request.on("end", function () { // Write headers to the response. // 200 is HTTP status code (this one means success) // Second parameter holds header fields in object // We are sending plain text, so Content-Type should be text/plain response.writeHead(200, { 'Content-Type': 'text/plain' }); // Send data and end response. response.end('Hello HTTP!'); }); // Listen on the 8080 port. }).listen(8080);
Este código é muito simples. Você pode enviar mais dados para o cliente usando o response.write()
método, mas você tem que chamá-lo antes de chamar response.end()
. Salve este código como http.js e digite o seguinte comando no seu console:
node http.js
Abra seu navegador e navegue até http://localhost:8080. Você deve ver o texto Olá Http! na página.
Manipulando parâmetros de URL
Como mencionei anteriormente, temos que fazer tudo sozinhos no Node, incluindo analisar argumentos de solicitação. Isso é, no entanto, bastante simples. Dê uma olhada no código a seguir:
// Include createServer import { createServer} from "http" // And url module, which is very helpful in parsing request parameters. url = require("url"); // Create the server. createServer(function (request, response) { // Attach listener on end event. request.on('end', function () { // Parse the request for arguments and store them in _get variable. // This function parses the url from request and returns object representation. var _get = url.parse(request.url, true).query; // Write headers to the response. response.writeHead(200, { 'Content-Type': 'text/plain' }); // Send data and end response. response.end('Here is your data: ' + _get['data']); }); // Listen on the 8080 port. }).listen(8080);
Este código usa o parse()
método do URL module, um módulo Node.js principal, para converter a URL da solicitação em um objeto. O objeto retornado tem um query
propriedade, que recupera os parâmetros da URL. Salve este arquivo como get.js e execute-o com o seguinte comando:
node get.js
Em seguida, navegue até http://localhost:8080/?data=put_some_text_here
no seu navegador. Naturalmente, alterando o valor do data
parâmetro não quebrará o script.
Lendo e gravando arquivos
Para gerenciar arquivos no Node, usamos o fs módulo (um módulo central). Lemos e escrevemos arquivos usando o fs.readFile()
e fs.writeFile()
métodos, respectivamente. Vou explicar os argumentos após o seguinte código:
// Include createServer, import { createServer } from "http" // And fs functions import { readFile, writeFile } from "fs" // Create the http server. createServer(function (request, response) { // Attach listener on end event. request.on("end", function () { // Read the file. readFile("test.txt", 'utf-8', function (error, data) { // Write headers. response.writeHead(200, { 'Content-Type': 'text/plain' }); // Increment the number obtained from file. data = parseInt(data) + 1; // Write incremented number to file. writeFile('test.txt', data); // End response with some nice message. response.end('This page was refreshed ' + data + ' times!'); }); }); // Listen on the 8080 port. }).listen(8080);
Salve isso como arquivos.js. Antes de executar este script, crie um arquivo chamado teste.txt no mesmo diretório que arquivos.js.
Este código demonstra a fs.readFile()
e fs.writeFile()
métodos. Toda vez que o servidor recebe uma solicitação, o script lê um número do arquivo, incrementa o número e grava o novo número no arquivo. o fs.readFile()
O método aceita três argumentos: o nome do arquivo a ser lido, a codificação esperada e a função de retorno de chamada.
Escrever no arquivo, pelo menos neste caso, é muito mais simples. Não precisamos esperar por nenhum resultado, embora você verifique se há erros em um aplicativo real. o fs.writeFile()
O método aceita o nome do arquivo e os dados como argumentos. Ele também aceita terceiro e quarto argumentos (ambos são opcionais) para especificar a codificação e a função de retorno de chamada, respectivamente.
Agora, vamos executar este script com o seguinte comando:
node files.js
Abra-o no navegador em http://localhost:8080 e atualize-o algumas vezes. Agora, você pode pensar que há um erro no código porque parece aumentar em dois. Isso não é um erro. Toda vez que você solicita essa URL, duas solicitações são enviadas ao servidor. A primeira solicitação é feita automaticamente pelo navegador, que solicita favicon.icoe, claro, a segunda solicitação é para o URL (http://localhost:8080).
Mesmo que esse comportamento não seja tecnicamente um erro, é um comportamento que não queremos. Podemos corrigir isso facilmente verificando o URL da solicitação. Segue o código revisado:
// Include createServer, import { createServer } from "http" // And fs functions import { readFile, writeFile } from "fs" // Create the http server. createServer(function (request, response) { // Attach listener on end event. request.on('end', function () { // Check if user requests / if (request.url == '/') { // Read the file. readFile('test.txt', 'utf-8', function (error, data) { // Write headers. response.writeHead(200, { 'Content-Type': 'text/plain' }); // Increment the number obtained from file. data = parseInt(data) + 1; // Write incremented number to file. writeFile('test.txt', data); // End response with some nice message. response.end('This page was refreshed ' + data + ' times!'); }); } else { // Indicate that requested file was not found. response.writeHead(404); // And end request without sending any data. response.end(); } }); // Listen on the 8080 port. }).listen(8080);
Teste agora; deve funcionar como esperado.
Acessando bancos de dados MySQL
A maioria das tecnologias tradicionais do lado do servidor tem um meio integrado de conexão e consulta a um banco de dados. Com o Node.js, você precisa instalar uma biblioteca. Para este tutorial, eu escolhi o estável e fácil de usar node-mysql. O nome completo deste módulo é [email protected] (tudo após o @ é o número da versão). Abra seu console, navegue até o diretório onde você armazenou seus scripts e execute o seguinte comando:
npm install mysql
Isso baixa e instala o módulo, e também cria o node_modules pasta no diretório atual. Agora vamos ver como podemos usar isso em nosso código; veja o seguinte exemplo:
// Include http module, import { createServer } from "http" // And mysql module you've just installed. import * as mysql from "mysql" // Create the connection. // Data is default to new mysql installation and should be changed according to your configuration. const connection = mysql.createConnection({ user: "root", password: "", database: "db_name" }); // Create the http server. createServer(function (request, response) { // Attach listener on end event. request.on('end', function () { // Query the database. connection.query('SELECT * FROM your_table;', function (error, rows, fields) { response.writeHead(200, { 'Content-Type': 'x-application/json' }); // Send data as JSON string. // Rows variable holds the result of the query. response.end(JSON.stringify(rows)); }); }); // Listen on the 8080 port. }).listen(8080);
Consultar o banco de dados com esta biblioteca é fácil; basta inserir a string de consulta e a função de retorno de chamada. Em uma aplicação real, você deve verificar se houve erros (o error
parâmetro não será undefined
se ocorrerem erros) e enviar códigos de resposta dependendo do sucesso ou falha da consulta. Observe também que definimos o Content-Type
para x-application/json
, que é o tipo MIME válido para JSON. o rows
parâmetro contém o resultado da consulta, e nós simplesmente convertemos os dados em rows
para uma estrutura JSON usando o JSON.stringify()
método.
Salve este arquivo como mysql.jse execute-o (se você tiver o MySQL instalado, ou seja):
node mysql.js
Navegar para http://localhost:8080 no seu navegador, e você deve ser solicitado a baixar o arquivo formatado em JSON.
Conclusão
Node.js requer trabalho extra, mas a recompensa de um aplicativo rápido e robusto vale a pena. Se você não quiser fazer tudo no nível mais baixo, sempre pode escolher algum framework, como o Express, para facilitar o desenvolvimento de aplicativos.
Node.js é uma tecnologia promissora e uma excelente escolha para um aplicativo de alta carga. Foi comprovado por corporações, como Microsoft, eBay e Yahoo. Se você não tiver certeza sobre como hospedar seu site ou aplicativo, sempre poderá usar uma solução VPS barata ou vários serviços baseados em nuvem, como Microsoft Azure e Amazon EC2. Ambos os serviços fornecem ambientes escaláveis a um preço razoável.
Originally posted 2022-05-27 20:19:42.