Node.js è un framework event-driven in grado di eseguire codice JavaScript sul server. Implementato sul V8 JavaScript Engine, il motore di Google Chrome, vanta una elevata performance nella compilazione del codice Javascript, da far invidia ad altri linguaggi dinamici come Python e Ruby.
Loop e non Thread
La natura event-driven di Node.js si manifesta nella gestione delle operazioni concorrenti: nei Web server tradizionali come Apache utilizziamo ad esempio un thread per elaborare ogni richiesta, mentre Node.js genera un nuovo evento che finirà in un unico processo, un "loop" che gestirà a suo tempo l'evento stesso eseguendo le relative funzioni di callback.
Il altre parole le funzioni più comuni di un server Web sono svolte da moduli diversi e gestite con eventi di input/output
. Una scelta particolarmente azzeccata visto che un server web trascorre maggior parte del tempo ad attendere l'esito di operazioni di input/output
, dunque la possibilità di lavorare in modo asincrono tramite funzioni di callback, offrono l'ambiente ideale per l'implementazione del JavaScript, migliorando l'efficienza della piattaforma.
Il primo avvio del server
Per cominciare possiamo scaricare il framework (attualmente alla versione stabile 0.4.12) e dopo averlo installato effettuiamo un test: includeremo il modulo per attivare il protocollo HTTP e creiamo una risposta HTTP di default da utilizzare come risposta alla richiesta del browser:
var http = require("http");
function onRequest(request, response) {
console.log("Richiesta ricevuta dal server");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Richiesta ricevuta");
response.end();
}
http.createServer(onRequest).listen(8080);
console.log("Server avviato");
una volta avviato il server web useguiamo lo script da console:
node ../path/server.js
colleghiamoci ora dal browser all'indirizzo http://localhost:8080/
per verificare l'effettivo funzionamento. Vediamo poi in dettaglio cosa fanno le istruzioni che abbiamo appena scritto.
Istanziato il modulo HTTP viene invocata la funzione createServer
, il quale restituisce un oggetto che referenzia il server, a questo punto l'esecuzione del metodo listen mette il web server in ascolto su una specifica porta (8080
). Il processo continuerà fino alla prossima richiesta, momento in cui il server si prende carico di inviare una risposta alla testata della richiesta HTTP, nel formato definito dal protocollo:
response.writeHead(statusCode, [reasonPhrase], [headers])
Lo statusCode
, formato da 3 caratteri, identifica il tipo di risposta, per esempio 404, il secondo argomento è opzionale, rappresenta un messaggio interpretabile anche ad un lettore "umano",
headers
è la risposta vera e propria.
Web Socket
Un altro punto di forza in Node.js è sicuramente l'implementazione della libreria Socket.io che permette di utilizzare la tecnologia Web Socket sul browser. Un esempio tipico di questa tecnologia sono le applicazioni real-time.
Dopo aver installato questa libreria, siamo in grado di far girare la parte server in uno script Node
ed intervenire sulla pagina client per mettere in comunicazione full-duplex i due sistemi, passando per il protocollo WS(WSS nel caso di protocollo con connessione sicura).
Sviluppiamo ora una chat stile Twitter
Il codice dello script Node
lato server ha il compito di rispondere alla richiesta con una pagina formato HTML:
var app = require('http').createServer(handler);
app.listen(8080);
function handler (req, res) {
fs.readFile(__dirname + '/test.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading test.html');
}
res.writeHead(200);
res.end(data);
});
}
e restare in ascolto sul protocollo WS in modo da filtrare gli eventi, per inviare al client i messaggi ricevuti dagli utenti. Gli eventi che ci interessano sono il message
ed il metodo send
, lanciato in esecuzione dall'oggetto socket, che inverà il messaggio al client, in modo da passare ad ogni browser tutti i messaggi ricevuti nelle richieste:
var io = require('socket.io').listen(app);
var fs = require('fs');
io.sockets.on('connection', function (socket) {
socket.on('message', function (data) {
socket.send(data);
console.log(data);
});
socket.on('disconnect', function(){
console.log('utente disconnesso');
});
});
Lato client, sviluppiamo un'interfaccia che permetta all'utente di inserire il messaggio da visualizzare. Gestiamo quindi gli eventi ed i metodi del WebSocket, messi a disposizione della libreria:
<scrpt src ="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('message', function(message) {
alert(message); //utilizziamo una struttura per contenere i messaggi
});
function sendMessage(){ //da lanciare al click sul bottone di invio messaggio
socket.send(message); //prelevare il messaggio dalla textarea e passarlo alla funzione
}
</script>
Il cuore della nostra applicazione lato client risiede nel metodo send()
, che riceve in ingresso una stringa da inviare al server in ascolto, e nella capacità di essere in ascolto sul evento message
per intercettare l'arrivo di eventuali messaggi.
Conclusioni
Node.js è un framework unix-like, utilizzabile anche a linea di comando, potreste creare una macchina virtuale con ambiente Linux, ed iniziare lo sviluppo. A differenza di altri framework, Javascript è utilizzato per lo sviluppo del server e con l'ausilio di specifiche estensioni è possibile avere il supporto di altri linguaggi, come PHP.