Introduzione a Node.js

Node.js è un framework che permette di realizzare web application usando un linguaggio di programmazione che utilizza la stessa sintassi di JavaScript.

Orientamento event-driven

Orientamento event-driven

Una caratteristica molto interessante di Node.js è l’orientamento verso lo sviluppo di codice asincrono. Questo approccio può sembrare innovativo per chi è abituato a lavorare con i normali linguaggi di programmazione server side. Paradigmi di programmazione come Java, Perl, .NET ecc. di solito implicano lo sviluppo di applicazioni sincrone nella gestione di richieste concorrenti. In molti casi ciò significa avere un oggetto di tipo server che esegue un ciclo di attesa su una specifica porta HTTP: per ogni richiesta viene recuperato un thread da un pool di thread in attesa, che si occuperà di gestire la comunicazione con il client. Ne segue che ogni richiesta viene trattata in modo sincrono, eventualmente sospendendo il thread durante l’attesa.

 

È proprio questo aspetto che ha suggerito il pattern di programmazione asincrono. Se confrontiamo i tempi di lavoro dei moderni processori con i tempi di trasmissione sul Web, otteniamo una differenza di parecchi ordini di grandezza. Le attese tra una richiesta HTTP e l’altra sono tempi lunghissimi rispetto al clock del processore. Da quest’osservazione nasce l’idea di ricorrere ad un approccio asincrono, dove il software lato server viene attivato solamente in seguito alla generazione di eventi particolari, come ad esempio: arriva una nuova richiesta, una delle risorse precedentemente richieste è pronta per essere restituita, ecc. Sono questi eventi ad attivare il codice Node.js, che per tal motivo è detto even driven.

Dal punto di vista di chi lavora abitualmente con JavaScript, o meglio ancora con le chiamate Ajax o l’oggetto XMLHttpRequest, questo approccio non presenta nulla di nuovo. La maggior parte del codice client side realizzato per girare nel browser usa un approccio asincrono, specialmente quando abbiamo a che fare con chiamate remote dirette verso il server. Per chi invece affronta l’argomento la prima volta, vediamo un semplice esempio che illustra il funzionamento asincrono del codice. Una chiamata sincrona funziona in questo modo

 

 

che implica il seguente timing di esecuzione: prima viene eseguita la chiamata alla getRemoteData. Se questa rimane in attesa, ad esempio perché deve aspettare la risposta del server remoto, l’esecuzione passa comunque alla riga successiva, ovvero all’istruzione di alert. Il risultato è che il nostro alert sarà errato, perché la variabile result non è ancora stata valorizzata.

Al contrario, una chiamata asincrona passa come argomento della funzione invocata un’altra funzione, che viene chiamata callback. Questa funzione è a tutti gli effetti un argomento come gli altri, con la differenza che verrà eseguita solamente quando il server esaudisce la richiesta. Avremo così

 

 

in questo caso, subito dopo l’esecuzione della chiamata alla funzione getRemoteData, il browser prosegue eseguendo l’alert “To be continued”. Al contrario, il codice all’interno della callback, cioè l’alert che visualizza la variabile result, rimane in attesa, risultando così asincrono rispetto al resto del codice. Questo codice verrà eseguito solo quando la variabile result viene valorizzata con la risposta del server.