Newsgroup: it.comp.lang.javascript
Titolo: [Newbie] Closures e Google Maps API

Ciao a tutti.
Sto usando Google Maps API per visualizzare un po' di indirizzi.
Ho un file XML con gli indirizzi che recupero, dopo aver caricato il
file, in un ciclo for
var markers = xml.documentElement.getElementsByTagName("address");
for(var i = 0; i < markers.length; i++) {
  var address = new Object();
 
address.name
 = markers[i].getAttribute("name");;
  address.icon = markers[i].getAttribute("icon");
  geocoder.getLocations(
address.name
, function(data, response) {
     getLocationsCallback(address, data, response);
  }
  );
}
Per ogni indirizzo, creo un Object e lo inizializzo con i campi che mi
interessano.
Per cercare gli indirizzi uso l'oggetto geocoder di tipo
GClientGeocoder precedentemente inizializzato.
Il metodo getLocations si attende due parametri: la location da cercare
ed una funzione con due parametri che saranno i dati trovati da
geocoder al termine del search ed un response code.
Siccome vorrei avere, quando questa funzione viene chiamata, anche
l'indirizzo che e' stato cercato (cosi' posso capire quali sono quelli
non trovati) ho wrappat il tutto in una closure che non fa altro che
richiamare
getLocationsCallback passando oltre ai dati del geocoder, anche
l'address su cui e' stata lanciata la ricerca.
Il risultato e' che su un file XML di 4 indirizzi, getLocationsCallback
viene chiamato correttamente 4 volte pero' il valore del primo
parametro e' sempre uguale all'ultimo indirizzo. Quindi con 4 indirizzi
A1, A2, A3, A4 address passato a getLocationsCallback vale sempre A4 in
tutte e 4 le chiamate.
Come si fa a far funzionare correttamente la cosa?
Grazie per i consigli.

 parametro e' sempre uguale all'ultimo indirizzo. 
E' normale, hai fatto una closure. Questi significa che le callback che hai
impostato condividono lo scope della funzione dove sono state definite. E
dato che nella funzione dove sono state definite, la variabile "address"
cambia ad ogni ciclo, questo si ripercuote ovviamente anche nelle callback.
-- 
~ Il lavoro č quel lasso di tempo che intercorre tra una pausa caffč
 e l'altra.


Si, questo l'avevo capito ormai.
Il problema era come fare quello che volevo, ovvero passare alla
closure un valore diverso ad ogni invocazione in modo che potesse
ricevere correttamente i 4 indirizzi differenti.
Comunque ho risolto grazie ad un illuminante post su
comp.lang.javascript. Basta creare una "closure factory", ovvero una
funzione che ritorna una funzione che viene usata come parametro per il
callback:
function getCallBackFor(address){
   return (function(data, response){
       getLocationsCallback(address, data, response);
    });
}
E nel codice di geocoder faccio
geocoder.getLocations(
address.name
, getCallBackFor(address));
E funziona correttamente.
Ciao

 callback:
Sinceramente le closure preferisco evitarle, se possibile. Con alcuni
browser, rischi comportamenti anomali e memory leaks (soprattutto con IE, e
quando c'č di mezzo il DOM, anche se non č questo il tuo caso).
-- 
~ "Non hai veramente capito qualcosa fino a quando non sei in grado
di spiegarlo a  tua nonna." (Einstein)


Si, ho letto di questi problemi.
Comunque non programmo in Javascript (mi serviva solo per fare uno
script usa e getta)... Capisco che comunque la giungla dei browser deve
essere un inferno! Speriamo che le cose migliorino visto che ormai con
AJAX le app web si sono elevate ad applicazioni di tutto rispetto.

 AJAX le app web si sono elevate ad applicazioni di tutto rispetto.
Eh, siamo ancora lontanucci...
-- 
~ Chi segue gli altri, non arriva mai primo.