Newsgroup: it.comp.lang.javascript
Titolo: Ancora un dubbio sull'esempio ajax di cui già discusso...

Allora, adesso il problema sembra essere piï¿œ circoscritto.
Ho semplificato l'esempio postato nel post precedente.
Stessa pagina "index.html".
Il file "test.js" adesso ï¿œ cosï¿œ:
 
 
function myFunction()
{
   var temp = null;
 
   function displayResponseData(request)
   {
      temp = request.responseText;
      document.getElementById("myDiv").innerHTML = temp;
   }
 
   makeRequest('ajax_info.txt', displayResponseData);
 
   window.alert(temp);   // !!!
}
 
 
la funzione "makeRequest" ï¿œ la stessa.
 
 
stesso file "ajax_info.txt" nella dir.
 
 
Eseguendo l'esempio il browser scrive correttamente
nella pagina il contenuto del file richiamato,
perï¿œ la stampa dell'alert riporta che la var "temp"
ï¿œ nulla. Ma come ï¿œ possibile ciï¿œ se la var ï¿œ
visibile all'interno della funzione ed ï¿œ stata
valorizzata dalla chiamata AJAX?
 

 valorizzata dalla chiamata AJAX?
 
sbagli il tempo del verbo :D
non "è stata", ma "sarà"; muFunction, pressappoco, ha questa "linea 
temporale"
 
 
 t0 - myFunction è invocata
 t1 - dichiaro variabile temp, con valore null
 t2 - dichiaro funzione displayResponseData
 t3 - invoco makeRequest
 t4 - makeRequest fa partire la richiesta di una GET http via javascript
 t5 - makeRequest termina
 t6 - eseguo window.alert
 t7 - l'utente preme ok, la popup si chiude
 t8 - myFunction termina
 t9 - il browser riceve la risposta della GET
t10 - viene invocata la funzione displayResponseData
t11 - viene assegnato alla variabile temp il valore della risposta
t12 - il contenuto del nodo del dom #myDiv è impostato
t13 - displayResponseData termina
 
 
-- 
ZeD

 t13 - displayResponseData termina
 
ma nel caso come si potrebbe fare allora per "imporre" una linea temporale
diversa da questa? (sempre considerando l'esempio in cui io vorrei che
la chiamata AJAX abbia solo il compito di caricare dei valori che poi vengono
usati in altri punti nel prosieguo del programma)
 

 diversa da questa?
 
Puoi usare chiamate sincrone, ma oggigiorno sono considerate il male e
si sta pensando di rimuoverle dall'oggetto XMLHttpRequest.
 
Il punto ï¿œ che non dovresti aver bisogno di "imporre una linea temporale
diversa", ma semplicemente capire come funziona la natura asincrona di
JavaScript, e sfruttarla. Se vuoi "imporre" ï¿œ perchï¿œ c'ï¿œ qualcosa che
non va nell'approccio che stai / vuoi utilizzare: devi rivedere il design.

 che poi vengono usati in altri punti nel prosieguo del programma)
 
Devi mettere dentro la callback tutto il codice che deve essere eseguito 
DOPO la conclusione della chiamata.
 
Se sei abituato a lavorare in sincrono (praticamente tutti gli altri 
linguaggi :) è un po' difficile entrare nella mentalità, ma sbatterci il 
muso come stai facendo tu, aiuta. :D
 
Bye.

 non va nell'approccio che stai / vuoi utilizzare: devi rivedere il design.
 
ok, sulla base di ciï¿œ rivedrï¿œ un po' quello che sto cercando di fare
ma soprattutto come lo sto cercando di fare ;-)
 

 Bye.
 
Ciao e grazie.
 
 

 callback,
 
Non devi. Il codice può essere benissimo spezzato, è il modo in cui lo
organizzi che cambia.
Un esempio sono gli eventi e le promises. Facciamo un esempio concreto.
Diciamo che hai una funzione `makeRequest` che fa una chiamata HTTP, e
quando ha terminato esegue `displayResponseData`. Diciamo che vuoi fare
anche un'altra operazione nel mezzo, qualcosa come salvare i dati che ti
arrivano come "stato" dell'applicazione o manipolarli prima di
visualizzarli, qualcosa come `handleData`. Avremmo quindi tre funzioni:
`makeRequest`, `handleData`, e `displayData`.
 
Ovviamente puoi fare l'operazione dentro `displayData`, ma noi vogliamo
fare le cose per benino e quindi avere funzioni che fanno compiti
specifici. Tu già usi la programmazione ad eventi, perché è cosí che il
browser lavora. Difatti, per eseguire la tua attuale
`displayResponseData`, attacchi un evento all'instanza di un oggetto
`XMLHttpRequest`: quando ha ricevuto i dati dal server, invia un
segnale; tutti quelli che stanno in ascolto di tale evento, vengono
notificati.
 
Fai lo stesso anche qui. Se hai un modello (model, MVC), potresti far sí
che `displayData` si "registri" all'evento del modello, che verrà
"emesso" da `handleData`. Altrimenti, potresti usare un Event Bus, che
in pratica è semplicemente un oggetto centrale dove tutti possono
rimanere in attesa di eventi emessi da qualunque cosa, e reagire. Il
vantaggio di questo approccio, è che è piú generico: i componenti che
sottoscrivono un dato evento, lo fanno sull'event bus, non sul soggetto
che emette l'evento, in questo modo si crea meno dipendenza perché
ignari dell'esistenza di chi ha emesso un dato evento, ma solo dei dati
che devono manipolare.
 
Le promises d'altro canto possono essere piú leggibili e utili in certi
contesti, soprattutto laddove il codice fa partire un compito (come una
richiesta HTTP) e deve elaborare ed eseguire codice in base a una
risposta. Non vengono usate per gestire eventi come click di un bottone,
ad esempio.
 
Usando le promises il tuo codice sarebbe simile a questo:
 
    makeRequest('ajax_info.txt').
        then(handleData).
        then(displayData);
 
Le promises per alcuni sono un po' ostiche da digerire, proprio per la
loro natura asincrona, ma sono state create appositamente per
semplificare certe situazioni, e non avere la famosa "piramide di
callback", come viene descritto bene all'inizio della famosa libreria Q:
 
 
http://documentup.com/kriskowal/q/
 
 
Personalmente non uso questa in quanto mastodontica per quello che le
promise devono fare, spesso basta qualcosa di piú light weight; ma il
concetto è quello.
 
Hope it helps.

 l'unico a cui accade?
 
/me alza la mano
 
-- 
ZeD

 concetto è quello.
 
jQuery implementa le promise (dalla 1.7 se non ricordo male), e mi pare 
si possano usare anche "al di fuori" della sua gestione eventi. Ho 
sentito che qualcuno si è lamentato perché non rispettano strettamente le 
specifiche definite da non-ricordo-chi, ma magari per un uso light vanno 
benone.
 
E ormai jQuery è diventata obbligatoria in ogni sito. ;P
 
Bye.

 Le promises d'altro canto possono essere piú leggibili e utili in certi
CUT
 
si ok, sembrano interessanti queste promises (che non conoscevo),
ma al momento non vorrei "iniettare" altri concetti avanzati
nella prototipizzazione dell'applicazione, in quanto appunto
trattasi di un semplice esempio di test per un'applicazione
ben pi� grande ed estesa alla quale non posso in questo momento
apportare nuove tecniche di programmazione. Questo anche perch�
gi� sto incontrando qualche problema con le chiamate AJAX e non
vorrei "inguaiarmi" con altre tecniche che si sovrappongono a
quanto gi� esiste.
 

 E ormai jQuery è diventata obbligatoria in ogni sito. ;P
 
non posso utilizzare jQuery... devo fare tutto a manina...
 

 quanto gi� esiste.
 
Le promises, cosí come altri "concetti" di cui parli, sono stati creati
appunto per risolvere molti dei problemi che s'incontrano con le
chiamate asincrone (e quindi AJAX). Se le ignori, rischi quindi di
trovarti in una situazione in cui nel peggiore dei casi hai del codice
error prone e poco manutenibile, e nel migliore di reinventare
parzialmente la ruota.
Soprattutto se stai lavorando a un'applicazione estesa, dovresti usare
le tecniche piú corrette per risolvere un dato problema. Se fosse un
semplice script di un sito, potresti anche farne a meno, ma per una web
app il discorso cambia.


 
E forse, ammesso che il problema tuo sia circoscritto all'encoding del
newsreader, dovresti vedere cosa intendo.
 
In un paio di casi pure il mio enconding risulta sballato – se noti il
thread – forse perché il newsreader ha fatto il reply usando il tuo, non
saprei, nel dubbio ho comunque cambiato le mie impostazioni.

 parzialmente la ruota.
 
capisco quello che dici, ma io prima voglio capire bene ci� che sta
dietro ad AJAX prima di avventurarmi in altri lidi.
 
 
 

 dietro ad AJAX prima di avventurarmi in altri lidi.
 
"AJAX" non è altro che l'oggetto XMLHttpRequest. Il tuo "capire bene
cosa ci sta dietro AJAX" non è altro che "capire come gestire la natura
asincrona di JavaScript". Le promise, fanno appunto questo: gestiscono
le chiamate asincrone. Non per nulla jQuery le ha implementate apposta
per le chiamate "AJAX".
 
Puoi benissimo studiarne l'implementazione, se vuoi capire come
funzionano – è il bello del web, e dell'Open Source.
 
Ma non confondere il problema che hai con lo strumento che usi. Non stai
cercando di "capire bene ciò che sta dietro ad AJAX" (anche perché non
vuol dire molto, scritta cosí), bensí come gestire la natura asincrona
delle sue chiamate: se le chiamate HTTP fossero state solo sincrone, non
avesti avuto alcun problema in merito, i tuoi codici avrebbero
funzionato fin da subito. L'uso di "AJAX" ha solo messo in luce il
problema che hai nel capire la programmazione asincrona in JS, ma non è
il problema.

 non posso utilizzare jQuery... devo fare tutto a manina...
 
???
 
a meno che non siano "compiti per casa", che altro motivo ci può essere per 
un vincolo del genere?
 
 
Comunque, se proprio hai tempo da perdere, su 
http://wiki.commonjs.org/wiki/Promises/A
 trovi le specifiche delle promises 
(teoricamente basterebbe il metodo when, in pratica alcune funzioni attorno 
aiutano).
 
Di re-implementare si possono re-implementare (ci sono riuscito persino io 
in un pomeriggio, figuriamoci!) ma secondo me fai prima a scegliere una 
libreria già fatta.
 
 
-- 
ZeD
 

 libreria già fatta.
 
Concordo completamente.
 

 opzionale.
 
eh, si, ovviamente volevo dire then(), che è l'unico metodo richiesto 
dall'interfaccia in modo esplicito.
 
(a mia discolpa, pensavo a when.js)
 
-- 
ZeD

 il problema.
 
Si questo l'ho capito... :-P