back to top

Funzioni di callback in Javascript

Le funzioni di un linguaggio di programmazione, come Javascript, consentono di passare come parametro non solo dei valori di tipo variabile o costante, ma anche altre funzioni che prenderanno il nome di funzioni di callback (in italiano funzioni di richiamo). Tali funzioni di callback, in genere (anche dato il nome "callback"), vengono eseguite dopo la routine principale, quindi al termine dell’esecuzione primaria lanciata dalla funzione chiamante.

Lo scopo delle funzioni di callback è quello di consentire a funzioni specifiche di svolgere comiti ulteriori a quelli loro propri, compiti che normalmente non sono noti al momento della scrittura del codice della funzione principale. In pratica si tratta di una tecnica (tipica della programmazione funzionale) grazie alla quale è possibile "espandere" le funzionalità predefinite di un blocco di codice, lasciando allo sviluppatore una maggiore libertà di sviluppo pur mantenendo un elevato grado di "riutilizzo" del codice sorgente.

Guardiamo un basilare esempio sintattico:

// definizione della funzione principale
function esempio(parametro, callback) {
  // Routine principale...
  // Callback...
}

La nostra funzione di esempio ha un parametro (potrebbe averne più di uno) e, in ultimo, un altro parametro che chiameremo callback, non perchè sia obbligatorio chiamarlo così, bensì per convenzione. Insomma, per coerenza.

La "funzione nella funzione" può essere opzionale o meno, a seconda di come viene controllata, ma in ogni caso sarà richiamata o direttamente definita all’interno del richiamo alla funzione principale, come nel seguente esempio di utilizzo:

// Creo una funzione secondaria
function foo() {
  // codice della funzione
}

// Richiamo la funzione principale specificando come callback il nome della funzione secondaria
// Attenzione: in questo caso il nome deve essere specificato senza gli apici (non è una stringa comune)
// ed omettendo le parentesi tonde!
esempio("Valore del parametro...", foo);

oppure:

// Richiamo la funzione principale
esempio("Valore del parametro...", function() {
  // Implemento direttamente il codice della funzione di callback...
});

La nostra prima callback

Facciamo un esempio concreto, programmando una semplice funzione che mostra una alert col nome dell’utente e che consente anche di gestire un’eventuale funzione come ultimo parametro:

function saluto(nome, cognome, callback) {
  alert('Ciao ' + nome + ' ' + cognome);
  if (callback && typeof callback === 'function') callback();
}

Nella nostra funzione di esempio abbiamo tre parametri, due stringhe ("nome" e "cognome") e l’ultimo parameto la funzione di richiamo, opzionale, monitorata attraverso la seguente funzione di controllo:

if (callback && typeof callback === 'function') callback();

Con questo controllo verifichiamo per prima cosa la presenza del parametro "callback", quindi verifichiamo che si tratti di una funzione (utilizzando il comando typeof e verificando che il valore sia function). Se la condizione passa, utilizziamo il nome del parametro aggiungendo le parentesi tonde aperta e chiusa per "trasformare" il parametro in funzione.

Potremmo quindi richiamare la funzione in modo semplice:

saluto('Mario', 'Rossi');

ottenendo semplicemente un alert con scritto:

Ciao Mario Rossi

oppure potremmo creare una funzione di richiamo al suo interno:

saluto('Mario', 'Rossi', function() {
  alert('Sei il benvenuto!');
});

ottenendo come risultato un secondo alert con scritto:

Sei il benvenuto!

In questo modo le due funzioni vengono eseguite in sequenza, nel senso che la nostra callback verrà lanciata non appena terminata l’istruzione primaria che la precede.

Gestire correttamente le temporizzazioni e le chiamate asincrone

Abbiamo detto che lo scopo di una funzione di callback è di essere eseguita, solitamente, dopo la routine principale. In merito a questa osservazione è necessario fare una puntualizzazione: ciò non è sempre vero quando si ha a che fare con delle temporizzazioni o con delle chiamate asincrone (Ajax). Facciamo un esempio.

function temporizzazione(ritardo, callback) {
  window.setTimeout(function() {
    document.write("Scusate il ritardo!");
  }, ritardo);
  if (callback && typeof callback === "function") callback();
}

In questo caso la routine principale è gestita mediante una temporizzazione che prevede un ritardo, pertanto Javascript passerà immediatamente (cioè senza attendere questo ritardo) all’istruzione successiva. In questo caso, quindi, la nostra funzione di cakkback verrà eseguita prima della principale.

Lo sviluppatore che predispone la funzione principale, pertanto, deve avere l’attenzione di gestire correttamente eventuali problemi legati ai tempi di esecuzione delle istruzioni. Per risolvere il problema, ad esempio, sarebbe stato sufficiente inserire il richiamo alla callback direttamente all’interno del metodo setTimeout in questo modo:

function temporizzazione(ritardo, callback) {
  window.setTimeout(function() {
    document.write("Scusate il ritardo!");
    if (callback && typeof callback === "function") callback();
  }, ritardo);
}

Così facendo, infatti, viene ripristinato l’ordine delle cose, in quanto il ritardo di esecuzione riguarderà tanto l’istruzione principale quanto la funzione di callback che, pertanto, tornerà ad essere l’ultimo blocco di esecuzione.

Lo stesso discorso va fatto se si utilizzano chiamate asincrone (Ajax): anche in questo caso, infatti, è opportuno inserire la funzione di calback all’interno del blocco logico che verifica la completa esecuzione ed il successo della chiamata, in caso contrario si potrebbero generare anomalie nel flusso di esecuzione del codice come quelle viste nell’esempio riguardante la cattiva gestione della temporizzazione.

function ajax(risorsa, callback) {
  var requestObj = false;
  if (window.XMLHttpRequest) {
    requestObj = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    requestObj = new ActiveXObject("Microsoft.XMLHTTP");
  }
  requestObj.open("GET", risorsa);
  requestObj.onreadystatechange = function () {
    if (requestObj.readyState == 4 && requestObj.status == 200) {
      alert(requestObj.responseText);
      if (callback && typeof callback === "function") callback();
    }
  }
  requestObj.send(null);
}

Passare il risultato della funzione principale alla funzione di callback

Vediamo infine come passare il valore elaborato dalla prima routine alla nostra funzione di callback in modo tale che quest’ultima possa effettuare operazioni sul risultato della funzione chiamante. Vediamo un esempio:

function somma(a,b,callback) {
  var risultato = (a + b);
  if (callback && typeof callback === "function") {
    risultato = callback(risultato);
  }
  return risultato;  
}

Come potete notare, in questa funzione effettuo il solito controllo per vedere se è stata prevista una funzione di callback ed in caso affermativo ne lancio l’esecuzione passandogli, come parametro, il risultato della routine principale (il risultato della somma di a + b). In questo caso la nostra funzione di callback assegnerà un nuovo valore alla variabile "risultato" alternado, di fatto, il valore di ritorno dalla funzione chiamante.

A questo punto il codice per richiamare la nostra funzione potrebbe essere qualcosa del genere:

var numero = somma(5,3,function(n) {
  return (n*n);
});
document.write(numero);

Con questa semplice funzione di callback prendiamo il valore ottenuto dalla somma di 5+3 (cioè 8) e lo eleviamo al quadrato (facciamo cioè 8×8) ottenendo come risultato 64.

Se la funzione di callbak non viene implementata direttamente nel codice di richiamo ma è esterna, il passaggio di parametri diviene più complicato. Non è possibile, infatti, richiamare direttamente la funzione di callback ma è necessario utilizzare "un intermediario" in questo modo:

// la funzione di calbak è implementata esternamente
function quadrato(n) {
  return (n*n);    
}

// eseguo il richiamo della funzione principale
// effettuando il richiamo della funzione secondaria definita esternamente
var numero = somma(5,3,function(n) {
  return quadrato(n)    
});
Pubblicitร 

Leggi anche...

Infinite scroll, come programmarlo su AMP e su Web con Javascript

L'infinite scroll è una tecnica di design e navigazione...

Codice Fiscale: 5 javascript per la verifica e il calcolo

Il codice fiscale รจ un identificativo tributario univoco che...

Math.ceil() – Arrotondare per eccesso con Javascript

Il metodo ceil() dell'oggetto Math di Javascript è utilizzato...

Minificare Javascript: librerie e strumenti online per comprimere il sorgente JS

La minificazione è un processo abbastanza diffuso nell'implementazione delle...

Javascript: svuotare un campo input o una textarea con un click

Quando si fornisce agli utenti un modulo per l'inserimento...

6 video player HTML5 per il tuo sito web

Con il rilascio delle specifiche definitive per HTML5 molte...
Pubblicitร