O Node.js está em alta no momento e facilita a criação de aplicativos da Web de alto desempenho e em tempo real. Ele permite que o JavaScript seja usado de ponta a ponta, tanto no servidor quanto no cliente. Este tutorial irá guiá-lo através da instalação do Node e do seu primeiro programa “Hello World”, para construir um servidor Twitter de streaming escalável.
O que é o Node.js?
Tradicionalmente, JavaScript só é executado no navegador da Web, mas recentemente tem havido um interesse considerável em trazê-lo para o lado do servidor também, graças ao projeto CommonJS. Outros ambientes JavaScript do lado do servidor incluem Jaxer e Narwhal. No entanto, o Node.js é um pouco diferente dessas soluções, porque é baseado em eventos e não em threads. Servidores da Web como o Apache que são usados para servir PHP e outros scripts CGI são baseados em encadeamento porque geram um encadeamento do sistema para cada solicitação recebida. Embora isso seja bom para muitos aplicativos, o modelo baseado em thread não se adapta bem com muitas conexões de longa duração, como você precisaria para servir aplicativos em tempo real como Friendfeed ou Google Wave.
“Toda operação de E/S no Node.js é assíncrona…”
Node.js, usa um loop de eventos em vez de threads e pode ser dimensionado para milhões de conexões simultâneas. Aproveita que os servidores passam a maior parte do tempo aguardando operações de E/S, como ler um arquivo de um disco rígido, acessar um serviço web externo ou esperar que um arquivo termine de ser carregado, pois essas operações são muito mais lentas do que nas operações de memória. Cada operação de E/S no Node.js é assíncrona, o que significa que o servidor pode continuar processando solicitações recebidas enquanto a operação de E/S está ocorrendo. JavaScript é extremamente adequado para programação baseada em eventos porque tem funções anônimas e encerramentos que tornam a definição de retornos de chamada em linha uma coisa fácil, e os desenvolvedores de JavaScript já sabem como programar dessa maneira. Esse modelo baseado em eventos torna o Node.js muito rápido e facilita muito o dimensionamento de aplicativos em tempo real.
Etapa 1 Instalação
O Node.js é executado em sistemas baseados em Unix, como Mac OS X, Linux e FreeBSD. Infelizmente, o Windows ainda não é suportado, portanto, se você for um usuário do Windows, poderá instalá-lo no Ubuntu Linux usando o Virtualbox. Para isso, siga este tutorial. Você precisará usar o terminal para instalar e executar o Node.js.
- Faça o download da versão mais recente do Node.js em nodejs.org (a versão mais recente no momento da redação deste artigo é 0.1.31) e descompacte-a.
- Abra o terminal e execute os seguintes comandos.
cd /path/to/nodejs make sudo make install
Muitas mensagens serão enviadas para o terminal enquanto o Node.js é compilado e instalado.
Passo 2 Olá Mundo!
Toda nova tecnologia começa com um “Hello World!” tutorial, então vamos criar um servidor HTTP simples que serve essa mensagem. Primeiro, no entanto, você precisa entender o sistema de módulos Node.js. No Node, a funcionalidade é encapsulada em módulos que devem ser carregados para serem utilizados. Há muitos módulos listados na documentação do Node.js. Você carrega esses módulos usando o require
funcionar assim:
var sys = require("sys");
Isso carrega o módulo sys, que contém funções para lidar com tarefas no nível do sistema, como imprimir a saída no terminal. Para usar uma função em um módulo, você a chama na variável em que armazenou o módulo, no nosso caso sys
.
sys.puts("Hello World!");
Executar essas duas linhas é tão simples quanto executar o node
comando com o nome do arquivo javascript como um argumento.
node test.js
Isso produzirá “Hello World!” para a linha de comando quando executado.
Para criar um servidor HTTP, você deve require
a http
módulo.
var sys = require("sys"), http = require("http"); http.createServer(function(request, response) { response.sendHeader(200, {"Content-Type": "text/html"}); response.write("Hello World!"); response.close(); }).listen(8080); sys.puts("Server running at http://localhost:8080/");
Este script importa o sys
e http
módulos e cria um servidor HTTP. A função anônima que é passada para http.createServer
será chamado sempre que uma solicitação chegar ao servidor. Uma vez que o servidor é criado, ele é instruído a escutar na porta 8080. Quando uma solicitação ao servidor chega, primeiro enviamos cabeçalhos HTTP com o tipo de conteúdo e código de status de 200 (bem-sucedido). Em seguida, enviamos “Hello World!” e feche a conexão. Você pode notar que temos que fechar explicitamente a conexão. Isso facilitará muito o fluxo de dados para o cliente sem fechar a conexão. Se você executar este script e for para http://localhost:8080/
no seu navegador, você verá “Hello World!”
Etapa 3 Um servidor de arquivos estático simples
OK, então construímos um servidor HTTP, mas ele não envia nada, exceto “Hello World”, não importa qual URL você vá. Qualquer servidor HTTP deve ser capaz de enviar arquivos estáticos, como arquivos HTML, imagens e outros arquivos. O código a seguir faz exatamente isso:
var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"); http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.sendHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Foundn"); response.close(); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.sendHeader(500, {"Content-Type": "text/plain"}); response.write(err + "n"); response.close(); return; } response.sendHeader(200); response.write(file, "binary"); response.close(); }); }); }).listen(8080); sys.puts("Server running at http://localhost:8080/");
Começamos exigindo todos os módulos que precisaremos em nosso código. Isso inclui o sys
, http
, url
, path
e fs
ou módulos do sistema de arquivos. Em seguida, criamos um servidor HTTP como fizemos antes. Desta vez, usaremos o url
módulo para analisar a URL de entrada da solicitação e encontrar o nome do caminho do arquivo que está sendo acessado. Encontramos o nome do arquivo real no disco rígido do servidor usando path.join
que une process.cwd()
, ou o diretório de trabalho atual, com o caminho para o arquivo que está sendo solicitado. Em seguida, verificamos se o arquivo existe, que é uma operação assíncrona e, portanto, requer um retorno de chamada. Se o arquivo não existir, uma mensagem 404 Not Found é enviada ao usuário e a função retorna. Caso contrário, lemos o arquivo usando o fs
módulo usando a codificação “binária” e envie o arquivo para o usuário. Se houver um erro na leitura do arquivo, apresentamos a mensagem de erro ao usuário e fechamos a conexão. Como tudo isso é assíncrono, o servidor pode atender a outras solicitações enquanto lê o arquivo do disco, não importa o tamanho dele.
Se você executar este exemplo e navegar para http://localhost:8080/path/to/file
esse arquivo será exibido em seu navegador.
Passo 4 Um Streamer de Tweets em Tempo Real
Com base em nosso servidor de arquivos estático, construiremos um servidor em Node.js que transmite tweets para um cliente que é servido por meio de nosso servidor de arquivos estático. Para começar, precisaremos de um módulo extra neste exemplo: o events
módulo. Node tem um conceito chamado de EventEmitter
, que é usado em todo o lado para manipular ouvintes de eventos para tarefas assíncronas. Assim como no jQuery ou em outra estrutura JavaScript do lado do cliente, onde você vincula ouvintes de eventos a coisas como cliques do mouse e solicitações AJAX, o Node permite vincular ouvintes de eventos a muitas coisas, algumas das quais já usamos. Isso inclui todas as operações de E/S, como ler um arquivo, gravar um arquivo, verificar se existe um arquivo, aguardar solicitações HTTP, etc. EventEmitter
abstrai a lógica de vincular, desvincular e acionar esses ouvintes de eventos. Estaremos usando um EventEmitter
para notificar os ouvintes quando novos tweets são carregados. As primeiras linhas do nosso streamer de tweets importam todos os módulos necessários e definem uma função para lidar com arquivos estáticos, que foi retirada do nosso exemplo anterior.
var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"), events = require("events"); function load_static_file(uri, response) { var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.sendHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Foundn"); response.close(); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.sendHeader(500, {"Content-Type": "text/plain"}); response.write(err + "n"); response.close(); return; } response.sendHeader(200); response.write(file, "binary"); response.close(); }); }); }
Temos usado o http
módulo para criar um servidor antes, mas também é possível criar um cliente HTTP usando o módulo. Estaremos criando um cliente HTTP para carregar tweets da timeline pública do Twitter, que é realizado pelo get_tweets
função.
var twitter_client = http.createClient(80, "api.twitter.com"); var tweet_emitter = new events.EventEmitter(); function get_tweets() { var request = twitter_client.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"}); request.addListener("response", function(response) { var body = ""; response.addListener("data", function(data) { body += data; }); response.addListener("end", function() { var tweets = JSON.parse(body); if(tweets.length > 0) { tweet_emitter.emit("tweets", tweets); } }); }); request.close(); } setInterval(get_tweets, 5000);
Primeiro, criamos um cliente HTTP na porta 80 para api.twitter.com e criamos um novo EventEmitter
. o get_tweets
A função cria uma solicitação HTTP “GET” para a linha do tempo pública do Twitter e adiciona um ouvinte de evento que será acionado quando os servidores do Twitter responderem. Como o Node.js é assíncrono, os dados no corpo da resposta vêm em partes, que são coletadas pelo ouvinte de “dados” da resposta. Este ouvinte simplesmente anexa o pedaço ao body
variável. Depois que todos os fragmentos chegam, o ouvinte “final” é acionado e analisamos os dados JSON recebidos. Se mais de um tweet for retornado, nós emit
o evento “tweets” em nosso tweet_emitter
, e passar a matriz de novos tweets. Isso acionará todos os ouvintes do evento ouvindo o evento “tweets” e enviará os novos tweets para cada cliente. Recuperamos os novos tweets a cada cinco segundos, usando setInterval
.
Finalmente, precisamos criar o servidor HTTP para lidar com as solicitações.
http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; if(uri === "/stream") { var listener = tweet_emitter.addListener("tweets", function(tweets) { response.sendHeader(200, { "Content-Type" : "text/plain" }); response.write(JSON.stringify(tweets)); response.close(); clearTimeout(timeout); }); var timeout = setTimeout(function() { response.sendHeader(200, { "Content-Type" : "text/plain" }); response.write(JSON.stringify([])); response.close(); tweet_emitter.removeListener(listener); }, 10000); } else { load_static_file(uri, response); } }).listen(8080); sys.puts("Server running at http://localhost:8080/");
Assim como fizemos com nosso servidor de arquivos estático, criamos um servidor HTTP que escuta na porta 8080. Analisamos a URL solicitada e, se a URL for igual a "/stream"
, nós cuidaremos disso, caso contrário, passaremos a solicitação para nosso servidor de arquivos estático. Streaming consiste em criar um ouvinte para ouvir novos tweets em nosso tweet_emitter
que será acionado por nossa get_tweets
função. Também criamos um temporizador para matar solicitações que duram mais de 10 segundos, enviando-lhes um array vazio. Quando novos tweets chegam, enviamos os tweets como dados JSON e limpamos o cronômetro. Você verá como isso funciona melhor depois de ver o código do lado do cliente, que está abaixo. Salve como test.html
no mesmo diretório que o JavaScript do lado do servidor.
Tweet Streamer
Aqui, temos uma página HTML simples que importa a biblioteca jQuery e define uma lista não ordenada para colocar os tweets. Nosso JavaScript do lado do cliente armazena em cache a lista de tweets e executa o load_tweets
funcionar após um segundo. Isso dá ao navegador tempo suficiente para terminar de carregar a página antes de iniciarmos a solicitação AJAX para o servidor. o load_tweets
função é muito simples: Ele usa jQuery getJSON
função para carregar /stream
. Quando uma resposta chega, percorremos todos os tweets e os adicionamos à lista de tweets. Então, chamamos load_tweets
novamente. Isso cria efetivamente um loop que carrega novos tweets, que expira após dez segundos devido ao tempo limite no servidor. Sempre que há novos tweets, eles são enviados para o cliente que mantém uma conexão contínua com o servidor. Essa técnica é chamada de sondagem longa.
Se você executar o servidor usando node
e vai para http://localhost:8080/test.html
você verá a linha do tempo pública do Twitter em seu navegador.
Próximos passos
O Node.js é uma tecnologia muito interessante que facilita a criação de aplicativos em tempo real de alto desempenho. Espero que você possa ver seu benefício e possa usá-lo em alguns de seus próprios aplicativos. Por causa do excelente sistema de módulos do Node, é fácil usar código pré-escrito em seu aplicativo, e há muitos módulos de terceiros disponíveis para praticamente tudo – incluindo camadas de conexão de banco de dados, mecanismos de modelagem, clientes de email e até estruturas inteiras conectando todos esses coisas juntas. Você pode ver uma lista completa de módulos no wiki do Node.js, e mais tutoriais do Node podem ser encontrados em How To Node. Eu também recomendo que você assista a um vídeo do JSConf, no qual Ryan Dahl, o criador do Node, descreve a filosofia de design por trás do Node. Isso está disponível.
Espero que tenham gostado deste tutorial. Se você tiver algum comentário, pode deixar um aqui ou me enviar uma mensagem no Twitter. Assentindo feliz!
Originally posted 2022-06-20 20:25:10.