ÉDITER:
J'ai oublié de dire que cette solution est en pure js, la seule chose dont vous avez besoin est un navigateur qui prend en charge les promesses https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise
Pour ceux qui ont encore besoin d'accomplir cela, j'ai écrit ma propre solution qui combine des promesses avec des délais d'attente.
Code:
/*
class: Geolocalizer
- Handles location triangulation and calculations.
-- Returns various prototypes to fetch position from strings or coords or dragons or whatever.
*/
var Geolocalizer = function () {
this.queue = []; // queue handler..
this.resolved = [];
this.geolocalizer = new google.maps.Geocoder();
};
Geolocalizer.prototype = {
/*
@fn: Localize
@scope: resolve single or multiple queued requests.
@params: <array> needles
@returns: <deferred> object
*/
Localize: function ( needles ) {
var that = this;
// Enqueue the needles.
for ( var i = 0; i < needles.length; i++ ) {
this.queue.push(needles[i]);
}
// return a promise and resolve it after every element have been fetched (either with success or failure), then reset the queue.
return new Promise (
function (resolve, reject) {
that.resolveQueueElements().then(function(resolved){
resolve(resolved);
that.queue = [];
that.resolved = [];
});
}
);
},
/*
@fn: resolveQueueElements
@scope: resolve queue elements.
@returns: <deferred> object (promise)
*/
resolveQueueElements: function (callback) {
var that = this;
return new Promise(
function(resolve, reject) {
// Loop the queue and resolve each element.
// Prevent QUERY_LIMIT by delaying actions by one second.
(function loopWithDelay(such, queue, i){
console.log("Attempting the resolution of " +queue[i-1]);
setTimeout(function(){
such.find(queue[i-1], function(res){
such.resolved.push(res);
});
if (--i) {
loopWithDelay(such,queue,i);
}
}, 1000);
})(that, that.queue, that.queue.length);
// Check every second if the queue has been cleared.
var it = setInterval(function(){
if (that.queue.length == that.resolved.length) {
resolve(that.resolved);
clearInterval(it);
}
}, 1000);
}
);
},
/*
@fn: find
@scope: resolve an address from string
@params: <string> s, <fn> Callback
*/
find: function (s, callback) {
this.geolocalizer.geocode({
"address": s
}, function(res, status){
if (status == google.maps.GeocoderStatus.OK) {
var r = {
originalString: s,
lat: res[0].geometry.location.lat(),
lng: res[0].geometry.location.lng()
};
callback(r);
}
else {
callback(undefined);
console.log(status);
console.log("could not locate " + s);
}
});
}
};
Veuillez noter que c'est juste une partie d'une plus grande bibliothèque que j'ai écrite pour gérer les trucs de Google Maps, donc les commentaires peuvent être déroutants.
L'utilisation est assez simple, mais l'approche est légèrement différente: au lieu de boucler et de résoudre une adresse à la fois, vous devrez passer un tableau d'adresses à la classe et elle gérera la recherche par elle-même, renvoyant une promesse qui , une fois résolu, renvoie un tableau contenant toutes les adresses résolues (et non résolues).
Exemple:
var myAmazingGeo = new Geolocalizer();
var locations = ["Italy","California","Dragons are thugs...","China","Georgia"];
myAmazingGeo.Localize(locations).then(function(res){
console.log(res);
});
Sortie de la console:
Attempting the resolution of Georgia
Attempting the resolution of China
Attempting the resolution of Dragons are thugs...
Attempting the resolution of California
ZERO_RESULTS
could not locate Dragons are thugs...
Attempting the resolution of Italy
Objet renvoyé:
Toute la magie se produit ici:
(function loopWithDelay(such, queue, i){
console.log("Attempting the resolution of " +queue[i-1]);
setTimeout(function(){
such.find(queue[i-1], function(res){
such.resolved.push(res);
});
if (--i) {
loopWithDelay(such,queue,i);
}
}, 750);
})(that, that.queue, that.queue.length);
Fondamentalement, il boucle chaque élément avec un délai de 750 millisecondes entre chacun d'eux, donc toutes les 750 millisecondes, une adresse est contrôlée.
J'ai fait quelques tests supplémentaires et j'ai découvert que même à 700 millisecondes, j'obtenais parfois l'erreur QUERY_LIMIT, alors qu'avec 750, je n'ai eu aucun problème.
Dans tous les cas, n'hésitez pas à modifier les 750 ci-dessus si vous vous sentez en sécurité en gérant un délai inférieur.
J'espère que cela aidera quelqu'un dans un proche avenir;)