EDITAR:
Olvidé decir que esta solución está en js puro, lo único que necesita es un navegador que admita promesas https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise
Para aquellos que todavía necesitan lograrlo, he escrito mi propia solución que combina promesas con tiempos de espera.
Código:
var Geolocalizer = function () {
this.queue = [];
this.resolved = [];
this.geolocalizer = new google.maps.Geocoder();
};
Geolocalizer.prototype = {
Localize: function ( needles ) {
var that = this;
for ( var i = 0; i < needles.length; i++ ) {
this.queue.push(needles[i]);
}
return new Promise (
function (resolve, reject) {
that.resolveQueueElements().then(function(resolved){
resolve(resolved);
that.queue = [];
that.resolved = [];
});
}
);
},
resolveQueueElements: function (callback) {
var that = this;
return new Promise(
function(resolve, reject) {
(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);
var it = setInterval(function(){
if (that.queue.length == that.resolved.length) {
resolve(that.resolved);
clearInterval(it);
}
}, 1000);
}
);
},
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);
}
});
}
};
Tenga en cuenta que es solo una parte de una biblioteca más grande que escribí para manejar cosas de Google Maps, por lo que los comentarios pueden ser confusos.
El uso es bastante simple, sin embargo, el enfoque es ligeramente diferente: en lugar de hacer un bucle y resolver una dirección a la vez, deberá pasar una matriz de direcciones a la clase y esta manejará la búsqueda por sí misma, devolviendo una promesa que , cuando se resuelve, devuelve una matriz que contiene todas las direcciones resueltas (y no resueltas).
Ejemplo:
var myAmazingGeo = new Geolocalizer();
var locations = ["Italy","California","Dragons are thugs...","China","Georgia"];
myAmazingGeo.Localize(locations).then(function(res){
console.log(res);
});
Salida de consola:
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
Objeto devuelto:
Toda la magia sucede aquí:
(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);
Básicamente, repite cada elemento con un retraso de 750 milisegundos entre cada uno de ellos, por lo que cada 750 milisegundos se controla una dirección.
Hice algunas pruebas adicionales y descubrí que incluso en 700 milisegundos a veces recibía el error QUERY_LIMIT, mientras que con 750 no he tenido ningún problema.
En cualquier caso, siéntase libre de editar el 750 anterior si se siente seguro manejando un retraso menor.
Espero que esto ayude a alguien en un futuro cercano;)