Migliorando il nostro codice

Indice

L’esempio precedente andava bene per un primo contatto, però , in un’applicazione reale, questo codice sarebbe piuttosto povero e difficile da mantenere, quindi cercheremo di aggiungere i seguenti miglioramenti:

  • Permettere di specificare la callback come parametro della funzione
  • Permettere di specificare qual è il nome del parametro nel quale si specifica la callback da richiamare in automatico, in caso che flickr sia jsoncallback
  • Aggiungere ulteriori parametri all’URL in modo semplice
  • Incapsulare il codice nello spazio dei nomi JSONP
    (‘le variabili globali sono un male‘)

Quindi, al lavoro! Prima di tutto ho messo lo schema per poi andare a riempirlo mano a mano:

Copia codice

var JSONP = {
  // Salva il riferimento allo script
  script: null,
  // Salva le opzioni specificate
  options: {},
  // Effettua la chiamata all'url specificato
  // seguendo le opzioni passate
  call: function(url, options){
  },
  // Riceve il risultato
  process: function(data) {
  }
};
Il metodo call
È il metodo che si occupa d’inviare la richiesta al server seguendo i parametri specificati. Il secondo parametro deve essere un oggetto con le seguenti proprietà:

  • callback: Il nome della funzione da eseguire quando arriva la risposta
  • callbackParamName: nome del parametro GET che definisce il nome della funzione da chiamare (ricorda jsoncallback nel caso di Flickr)
  • params: un oggetto del tipo chiave-valore da serializzare e incorporarlo nell’URL

Un esempio dell’oggetto options sarebbe:

Copia codice

var options = {
  callback:  miaFunzione,
  callbackParamName: "jsoncallback",
  params: {
    a=1,
    b=2
  }
};
E questo sarebbe il codice del metodo:
Copia codice

call: function(url, options){
  // Verifica le opzioni
  if(!options) this.options = {};
  this.options.callback = options.callback || function(){};
  this.options.callbackParamName = options.callbackParamName || "callback";
  this.options.params = options.params || [];
  // Determina se aggiungere un parametro
  // separato da ? o da &
  var separator = url.indexOf("?") > -1? "&" : "?";
  // Serializza l'oggetto in una stringa di testo
  // con formato URL
  var params = [];
  for(var prop in this.options.params){
    params.push(prop + "=" + encodeURIComponent(options.params[prop]));
  }
  var stringParams = params.join("&");
  // Crea lo script o cancella l'utilizzato in precedenza
  var head = document.getElementsByTagName("head")[0];
  if(this.script){
    head.removeChild(script);
  }
  script = document.createElement("script");
  script.type = "text/javascript";
  // Aggiunge e carica lo script,
  // indicando di chiamare JSONP.process
  script.src = url + separator + stringParams + (stringParams?"&":"") + this.options.callbackParamName +"=JSONP.process";
  head.appendChild(script);
}
Credo che non ci sia molto da spiegare, poiché migliora solo la base precedente, solo la logica cambia appena.
Il metodo process
Questa è la funzione che nostro codice forza a eseguire una volta che i dati vengono caricati: qui si possono fare i compiti ordinari di deserializzazione di dati, controllo degli errori, ecc. Nel nostro caso serve solo da ponte tra il server e il callback specificato.
Copia codice

process: function(data) {
  // Qui si possono fare
  // le operazioni comuni per trattare i dati
  this.options.callback(data);
}
Dopo aver visto i metodi, vediamo di provarlo.