Visualizzazione post con etichetta github. Mostra tutti i post
Visualizzazione post con etichetta github. Mostra tutti i post

martedì, dicembre 02, 2014

Impariamo a definire i nostri ravioli .. ehm ... moduli in node.js

Node.js è stato disegnato all'insegno della modularità.
Abbiamo già notato come esista una pletora di moduli utilizzabili da un programma node.js:
basta utilizzare l'istruzione require('nomemodulo') per utilizzare le funzionalità esportate dal modulo.

La piattaforma provvede una serie di moduli inclusi nella distribuzione di base, abbiamo visto ad esempio l'utilizzo del modulo fs o del modulo path

In questo post impariamo a definire i nostri moduli da utilizzare nei nostri programmi, per cercare di programmare utilizzando ravioli e non spaghetti

Una volta definito un modulo, è anche possibile pubblicarlo sul repository ufficiale dei moduli gestiti da npm.

Date un'occhiata alla lista ufficiale di moduli per node disponibili attualmente.

Se vi piace un modulo, basterà eseguire in una shell il comando npm  <nomemodulo> nella cartella radice del progetto che state sviluppando, per poterlo utilizzare con una istruzione di require('nomemodulo') dal vostro codice.

Ad esempio, supponete di aver bisogno della funzionalità di trasformazione dei vostri oggetti json in formato xml: basterà utilizzare il modulo di terze parti che si chiama xml registrato sul repository ufficiale.

Vi posizionate nella cartella del vostro progetto e digitate npm install xml: verrà creata una directory node_modules, all'interno del vostro progettoche contiene i sorgenti del modulo, se un modulo dipende da altri moduli, questi verranno a loro volta scaricati in locale, tutto in maniera semplice e trasparente.

Ogni modulo ufficiale ha una pagina di documentazione come questa in cui ci sono le informazioni su come utilizzarlo.

In questo caso basta scrivere del codice di questo tipo
 var xml = require('xml');  
   
 var xmlString = xml({libri :   
      [  
           {  
                libro: [  
                     {titolo : 'Il signore degli anelli'},   
                     {autore : 'Tolkien'}  
                ],  
           },  
           {  
                libro: [  
                     {titolo: 'Guerra e pace'},  
                     {autore: 'Tolstoj'}  
                ]  
           }  
      ]  
 }, true);  
   
 console.log(xmlString);  
Per ottenere sulla console
 <libri>  
   <libro>  
     <titolo>Il signore degli anelli</titolo>  
     <autore>Tolkien</autore>  
   </libro>  
   <libro>  
     <titolo>Guerra e pace</titolo>  
     <autore>Tolstoj</autore>  
   </libro>  
 </libri>  
I singoli moduli devono essere definiti in un file, il cui nome sarà il nome del modulo, all'interno del file si deve utilizzare una istruzione del tipo module.exports = {}: assegniamo alla proprietà export dell'oggetto globale module un qualsiasi oggetto che definiremo noi, magari una iife per incapsulare dettagli implementativi mediante il meccanismo delle closure.

Facciamo un esempio.
Immaginiamo di implementare un modulo biblioteca che ci permetta di salvare in memoria dei libri e di ottenere la lista attuale dei libri.

Il programma principale utilizza il modulo biblioteca
 var biblioteca = require('./biblioteca');  
   
 biblioteca.inserisciLibro({  
      titolo : "Il signore degli anelli",  
      autore : "Tolkien"  
 });  
   
 biblioteca.inserisciLibro({  
      titolo : "Guerra e pace",  
      autore : "Tolstoj"  
 });  
   
 biblioteca.elaboraLibri(function(error, libri) {  
      if (error)  
           console.log(error.messaggio);  
      else {  
           libri.forEach(function(libro) {  
                console.log("Titolo: " +   
                          libro.titolo +   
                          "- Autore: " +   
                          libro.autore);  
           });  
      }  
 });  
Il modulo biblioteca dovrà essere implementato in un file dal nome biblioteca.js presente nella stessa cartella del file programma.js che rappresenta il programma principale.
 module.exports = (function() {  
      var libri = [],  
          inserisciLibro = function(libro) {  
             libri.push(libro);  
          },  
          elaboraLibri = function(callback) {  
             if (libri.length === 0)  
                callback({messaggio: 'biblioteca vuota'}, null);  
             else  
                callback(null, libri);       
          };  
          
          return {  
             inserisciLibro : inserisciLibro,  
             elaboraLibri : elaboraLibri  
          };  
 })();  
Notate la prima istruzione che assegna a module.exports il risultato di una funzione che viene eseguita immediatamente, tale risultato è un oggetto che espone solo i metodi inserisciLibro ed elaboraLibri.

Notate anche l'utilizzo di una funzione di callback definita in programma.js e passata come argomento a eleboraLibri, tale funzione di callback verrà eseguita solo se non ci sono condizioni di errore (in questo caso rappresentate da una biblioteca vuota).

Ho aggiornato su github il progetto, effettuate un git pull per aggiornare i sorgenti che avete in locale, come mostrato questo post.
Ricordatevi, per il progetto esempio-xml, di posizionarvi nella cartella radice ed eseguire npm install xml per includere il modulo xml nel progetto.

Se avete dubbi e/o domande, commentate!

Alla prox.
Ivan


mercoledì, novembre 26, 2014

Ajax in azione

Con questo post, vi mostrerò come implementare richieste asincrone ad un componente server.

Per rendere l'esempio funzionante, ho creato una piccola applicazione web che risponde ad ogni richiesta che riceve, con la lista di due libri in formato json.

La richiesta partirà in modalità asincrona da questa stessa pagina che risiede su un dominio (blogger.com)  diverso da quello su cui è installata la mia applicazione (herokuapp.com)

Per motivi di sicurezza, non sarebbe possibile fare richieste asincrone in javascript ad un dominio diverso da quello da cui proviene il frammento javascript stesso. (same-origin policy)

Per effettuare una richiesta asincrona ad un server, utilizzando javascript standard, si utilizza un codice di questo tipo, dove ho omesso, per semplicità, eventuali controlli d'errore
  
 var xmlhttp = new XMLHttpRequest();  
 xmlhttp.onreadystatechange=function() {  
   document.getElementById("contenitore").innerHTML= xmlhttp.responseText;  
 };  
 xmlhttp.open("GET","risorsa/?eventualeparametro=valore",true);  
 xmlhttp.send();  

I passi per eseguire una richiesta asincrona sono i seguenti:
  1. istanziare un oggetto con la funzione costruttore XMLHttpRequest
  2. configurare su questo oggetto la funzione di callback che sarà eseguita quando arriverà la risposta dal server
  3. configurare il tipo di richiesta, in questo caso GET, e l'indirizzo della risorsa a cui effettuare la richiesta, che deve risiedere sullo stesso server, concatenendo all'indirizzo eventuali parametri
  4. mandare, in modalità asincrona, la richiesta: la send ritorna subito, non è bloccante. 
  5. appena il server risponde, cambierà lo stato dell'oggetto XMLHttpRequest e dunque verrà eseguita la funzione di callback che, in questo caso, riempirà il nodo che ha id = 'contenitore' con la risposta che è arrivata dal server
Se provassimo ad utilizzare questo frammento di codice utilizzando l'indirizzo reale dell'applicativo che ho sviluppato (https://ajaxjsonpexample.herokuapp.com/),  non otterremmo il risultato sperato, per il noto problema della same-origin policy.

Per ovviare a questa limitazione, nel tempo sono nate una serie di veri e propri hack, il piu' utilizzato dei quali va sotto il nome di jsonp, dove p sta per padding .

In sintesi, si deve fare in modo che la risorsa server ritorni i dati effettivi in formato json, come se fossero il parametro di una funzione:

 callback([{titolo: 'Il signore degli anelli'},{titolo: 'guerra e pace'}])  

La mia applicazione, ritorna al chiamante proprio questa stringa.

Se aggiungiamo alla nostra pagina, dinamicamente, un nodo script il cui attributo src punti all'indirizzo della mia applicazione web, il run time javascript interpreterebbe la risposta del server come una istruzione da eseguire

 callback([{titolo: 'Il signore degli anelli'},{titolo: 'guerra e pace'}])  

Ci basta allora aggiungere una proprietà dal nome callback sull'oggetto globale window, di tipo funzione, che gestisca l'array di libri ricevuti come parametro.

Provate a cliccare il bottone seguente




Ho messo l'implemetazione dell'esempio (codice lato client) su github. Fate riferimento a questo post per capire come fare ad ottenerli sulla vostra macchina.

Se aprite i web tools con F12 e andate sul tab networking e poi script, e cliccate di nuovo il bottone,potrete effettivamente osservare la richiesta fatta al server esterno con la relativa risposta.



In un prossimom post vi parlerò di heroku e di come sia facile pubblicare una nostra applicazione web su questa piattaforma di hosting che supporta già ruby,php,nodejs,java,python,scala,clojure.

L'applicazione web che ho installato su heroku è scritta in java, è costituita da una semplice servlet che scrive direttamente sulla risposta la stringa json che rappresenta l'array dei due libri.

Alla prox.
Ivan

martedì, novembre 18, 2014

Un pò di pratica

Non c'è niente di meglio che un pò di pratica per capire i concetti esposti fino ad ora.

Per l'occasione ho creato un progetto su GitHub, dove metterò di volta in volta tutto il materiale necessario per eseguire gli esempi che proporrò.

Git è un sistema di condivisione sorgenti distribuito.

Ognuno di voi potrà installare sulla sua macchina il repository dei sorgenti eseguendo un semplice comando da una shell, a patto di installare git per il proprio sistema operativo.

Se non usate ancora git, vi consiglio di provarlo, poi non potrete farne a meno.

Scaricatelo e installatelo seguendo questo link e scegliendo il pacchetto d'installazione in base al sistema operativo utilizzato.


  • Aggiungete al path di sistema la cartella bin presente nel percorso d'installazione
  • Create una cartella vuota che conterrà tutti gli esercizi che vi proporrò.
  • Aprite una shell nuova e posizionatevi nella cartella appena creata.
  • Eseguite il comando:
    git clone https://github.com/ivansaracino/passionejavascript.git


Il comando precedente copierà nella vostra cartella la cartella passionejavascript

Quando aggiornerò il repository remoto, vi basterà invocare il comando

  • git pull

dalla cartella radice passionejavascript.

Nella cartella passionejavascript troverete la cartella modulerevealedpattern contenente la soluzione al seguente esercizio:

Creare una pagina web con due bottoni, start e stop.
Appena caricata la pagina, il bottone start è abilitato, il bottone stop è disabilitato.
Quando premete il bottone start, dovrà partire un contatore, che si aggiornerà ogni secondo; a questo punto il bottone start diventa disabilitato e il bottone stop abilitato.
Quando premete il bottone stop, il contatore si arresterà e così via.

L'esempio non è particolarmente utile ma mostra l'utilizzo del module revealed pattern,  un design pattern in javascript, che ha lo scopo di esporre sullo scope global un unico oggetto, sfruttando il concetto di closure e IIFE che abbiamo visto in questo post

Per eseguire la soluzione vi basta aprire il file index.html in un browser.

Notate come nello scope globale ci sia solo la variabile modulo  che espone le funzioni start() e stop() legate ai click dei rispettivi bottoni presenti nella pagina html.

Tutti i dettagli implementativi sono nascosti nella IIFE.

Se avete dubbi o problemi, non fate i timidi: chiedete commentando :))

Alla prox
Ivan