Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 9 di 24
  • livello principiante
Indice lezioni

I parametri - II

Assegnare correttamente una funzione al parametro onreadystatechange
Assegnare correttamente una funzione al parametro onreadystatechange
Link copiato negli appunti

A completare la lista dei parametri utili ecco onreadystatechange. Nella bozza di lavoro del W3C si parla di questo parametro come gestore di evento. In effetti il parametro serve ad assegnare una funzione che viene chiamata al variare del readyState.

Quando in JavaScript si assegna un metodo si è soliti sfruttare il referente this all'interno dello stesso al fine di essere certi che quanto richiesto faccia parte dello scope di tale oggetto. Chiariamo questo concetto con un esempio:

Listato 11. Assegnamento generico di un metodo ad un oggetto

var oggetto = new Object();
oggetto.testo = "html.it";
oggetto.funzione = function() {
  alert(this.testo);
};

// una volta richiamato il metodo dell'oggetto ...
oggetto.funzione();
// la finestra di alert comunicherà
// html.it
// stringa presente all'interno del parametro oggetto.testo

Il comportamento appena descritto è più che normale, essendo funzione un metodo dell'oggetto, ma cosa accadrebbe se si scegliesse di richiamare in modo asincrono lo stesso metodo?

Listato 12. Richiamiamo il metodo in modo asincrono

var oggetto = new Object();
oggetto.testo = "html.it";
oggetto.funzione = function() {
  alert(this.testo);
};

setTimeout(oggetto.funzione, 50);
// risultato dopo 50 millisecondi una finestra con scritto
// undefined

Per risalire al campo testo all'interno dello stesso oggetto è indispensabile utilizzare il nome dell'oggetto stesso come referente e non più this.

Sostituiamo quindi alert(this.testo); con alert(oggetto.testo);. Questo è l'unico modo per raggiungere il parametro testo dell'oggetto utilizzato.

Il concetto vale allo stesso identico modo anche per la funzione assegnata ad onreadystatechange, contenendo a sua volta una funzione richiamata in modo asincrono. All'interno di questa funzione scriviamo i controlli in base ai parametri descritti ma il referente dovrà comunque essere il nome dell'oggetto e non this.

Listato 13. Esempio di funzione assegnata a onreadystatechange

ajax.onreadystatechange = function() {
  if(ajax.readyState === 4) {
  if(ajax.status == 200)
    alert("Operazione effettuata con successo");
  else
    alert("Operazione fallita, errore numero " + ajax.status);
  }
}

Ultimo minuzioso ed avanzato dettaglio prima di passare ad un esempio concreto, sconsigliabile a chi non ha troppa familiarità col JavaScript, è un piccolo approfondimento sul momento giusto in cui dichiarare onreadystatechange.

Essendo richiamato in modo asincrono non è sbagliato assegnarlo dopo aver richiamato i metodi open e send. Il vantaggio è quello di evitare che la funzione assegnata, potenzialmente molto complessa, venga richiamata inutilmente più volte prima che readyState abbia un valore pari a 4. Anche senza questo accorgimento difficilmente abbiamo rallentamenti ma perchè non ottimizzare?

L'esempio pratico di un flusso dati asincrono è rappresentabile in questo modo:

Listato 14. Esempio di flusso asinrono

var oggetto = new Object();
oggetto.funzione = function() {
  alert(oggetto.testo);
};

// imposto un timeout ancora prima di assegnare
// il parametro testo
setTimeout(oggetto.funzione, 0);

// finestra di avviso corretta!
oggetto.testo = "html.it";

Il valore del parametro testo, la stringa "html.it", viene assegnato solo dopo aver impostato il timeout sul metodo oggetto.funzione con ritardo pari a zero millisecondi.

Potremmo pensare che la chiamata a tale metodo sia quindi immediata e che il parametro testo risulti "undefined" poichè definito dopo il setTimeout.

In realtà non è così perchè gli intervalli di tempo, non sincronizzati con il normale flusso di esecuzione, vengono richiamati solo dopo che tutto il codice è stato processato per intero.

L'interprete infatti prima assegnerà al parametro testo il valore "html.it" e solo alla fine richimerà tutti gli eventi asincroni incontrati durante la lettura del codice, in questo caso il setTimeout con latenza 0 per il metodo oggetto.funzione.

L'unico modo per eliminare questa certezza è richiamare tra una chiamata asincrona, setTimeout o setInterval, una finestra di tipo "modal", come alert o prompt.

Inserendo una di queste dialog tra il setTimeout e l'assegnazione del valore "html.it" al parametro testo, il flusso di esecuzione verrà interpretato solo fino a quel punto, gli intervalli asincroni assegnati fino a quel punto saranno richiamati e solo dopo, la finestra di avviso, verrà mostrata.

Ad esempio mettendo alert("prova"); tra il setTimeout e la linea oggetto.testo = "html.it"; sarà possibile notare un'avviso con valore "undefined", ovvero l'esecuzione del setTimeout sul metodo oggetto.funzione e solo dopo l'alert con la scritta prova.

L'avviso con "undefined" confermerà quindi che il parametro testo non è stato ancora assegnato e che la funzione alert ha modificato in qualche modo il flusso di esecuzione del codice, interrompendone l'interpretazione fino a quel punto.

Il consiglio è quindi di assegnare onreadystatechange dopo il send, ma evitando che tra il send e questa assegnazione vi sia codice per debug o altro che contenga un evento di tipo modal.

Per non avere problemi di sorta, il punto migliore in cui assegnare quest'ultimo parametro sarebbe tra open e send, come mostrato per comodità nei prossimi esempi. Farlo prima di richiamare open risulterebbe possibile ma completamente inutile.

Ti consigliamo anche