2011-09-23 5 views
1

Je souhaite placer des marqueurs sur une carte. La source est une requête json, qui renvoie des villes.Rappels sur les rappels

J'ai une fonction (sencha) qui retourne les enregistrements (asynchrone) et une fonction (google maps api) qui renvoie le lng, lat pour des villes spécifiques (asynchrone) et une méthode (google maps), qui met marqueurs sur la carte.

Le résultat devrait être un marqueur sur la carte à l'emplacement calculé par google avec une légende récupérée de l'enregistrement.

records de charge

offers = App.stores.offers.load({ 
    callback: function(records, operation, success){...} 
}) 

get emplacement

geocoder = new google.maps.Geocoder(); 
geocoder.geocode(
    {'address': adress}, 
    function(results, status) {...} 
} 

et le marqueur mis

marker = new google.maps.Marker({ 
    map: map, 
    position: loc, 
    title: text 
}); 

Ce que je wan't à faire est, charger l'enregistrement, boucle sur chaque enregistrement , renseignez-vous sur l'emplacement de la ville et placez un marqueur.

synchrone je ferais:

records = App.stores.offers.load(); 
    for (var i=0; i < records.length; i++) { 
    setMarker(map, getLocation(records[i].data["city"]), cords[i].data["text"]); 
    } 

Quelle est la bonne façon de le mettre en même temps que les fonctions asynchrones?

Répondre

0

Je ne sais pas vraiment ce que la fonction App.stores.offers.load fait exactement, mais je suppose que ses arguments de fonction de rappel contiennent des résultats de chargement dans la variable enregistrements. Dans ce cas, parcourez les enregistrements à l'intérieur de la fonction de rappel et pour chaque géocode d'appel, ainsi que sur les marqueurs de lieu de rappel du géocodage (rien de mal à cela).

EDIT: cela est non testé et probablement pas la plus efficace, mais devrait fonctionner:

offers = App.stores.offers.load({ 
    callback: function(records, operation, success){ 
     if (success) {//or sth like this 
      var complete; 
      for (var i = 0; i < records.length; i++) { 
       complete = false; 
       geocoder.geocode({'address': records[i].adress}, 
        function(results, status) { 
        if (status == google.maps.GeocoderStatus.OK) { 
         map.setCenter(results[0].geometry.location); 
         var marker = new google.maps.Marker({ 
          map: map, 
          title: results[i].text, 
          position: results[0].geometry.location 
         }); 
        } else { 
         alert("Geocode was not successful for the following reason: " + status); 
        } 
        complete = true; 
       }); 
       while (!complete); 
      } 
     } 
    } 
}); 
+0

En fait, ce fut ma première supposition aussi, mais si je dois le texte à partir des dossiers [i] .text pour définir le titre des marqueurs, cela ne fonctionnera pas .. – Beffa

+0

vous n'étiez pas très clair sur ce dont vous avez besoin, je vais essayer de comprendre sth – slawekwin

+0

Pourquoi les résultats devraient [i] stocker le texte? Parce que c'est "i" asynchrone est dans le rappel de "geocode" pas ce que vous attendez, c'est probablement records.length, parce que la boucle est (beaucoup) plus rapide que d'obtenir la réponse de google back. – Beffa

0

En fin de compte, je mis en œuvre avec ExtJS/sencha. Le deuxième problème que j'ai rencontré était les restrictions sur le service google maps (j'avais beaucoup de quota dépassé les exceptions). Ce n'est donc pas exactement la réponse à la question. J'ai donc marqué l'autre réponse comme correcte, parce que c'est plus proche de la question. Voici le code que j'ai eu à la fin de toute façon, peut-il aider quelqu'un.

App.stores.offers = new Ext.data.Store({ 
model: 'Offer', 
(...) 

listeners: { 
    load: function(store, records, success){ 
    this.addEvents("refresh_locations", "locations_updated"); 
    for (var i=0; i < store.data.length; i++) { 
    store.fireEvent("refresh_locations", store , store.getAt(i), "load"); 
    } 
}, 
refresh_locations: function(store, record, method){ 
    if (record.get("location") == null || record.get("location") == ""){ 
    Ext.Ajax.request({ 
     url: 'api/partner2sport/find_location', 
     params: { 
     "city" : record.get("place") 
     }, 
     success: function(response, options) { 
     db_check = Ext.decode(response.responseText)["success"]; 
     if (db_check){ 
      var latlngStr = Ext.decode(response.responseText)["location"].replace(/\(|\)/g,"").split(",",2) 
      var lat = parseFloat(latlngStr[0]) - (Math.random()/100); 
      var lng = parseFloat(latlngStr[1]) - (Math.random()/100); 
      var latlng = new google.maps.LatLng(lat, lng); 
      record.set("location", latlng); 
     }else{ 
      geocoder = new google.maps.Geocoder(); 
      geocoder.geocode(
      { 
       'address': record.get("place") 
      }, 
      function(results, status) { 
       if (status == google.maps.GeocoderStatus.OK) {    
       record.set("location", results[0].geometry.location); 
       Ext.Ajax.request({ 
        url: 'api/partner2sport/set_location', 
        params: { 
        "city" : record.get("place"), 
        "location": record.get("location") 
        } 
       }); 
       } 
      } 
     ); 
     } 
     }, 
     failure: function(response, options) { 
     console.log("bad request"); 
     } 
    }); 
    } 
}, 

(...)

+0

et comment vérifiez-vous quel résultat de géocodage avez-vous reçu? – slawekwin

+1

Pourriez-vous me relire le code? – SteveCav