BEARBEITEN:
Ich habe vergessen zu sagen, dass diese Lösung in reinem js vorliegt. Sie benötigen lediglich einen Browser, der Versprechen unterstützt. Https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Promise
Für diejenigen, die dies noch tun müssen, habe ich meine eigene Lösung geschrieben, die Versprechen mit Timeouts kombiniert.
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);
}
});
}
};
Bitte beachten Sie, dass dies nur ein Teil einer größeren Bibliothek ist, die ich für Google Maps geschrieben habe. Daher können Kommentare verwirrend sein.
Die Verwendung ist recht einfach, der Ansatz ist jedoch etwas anders: Anstatt jeweils eine Adresse zu schleifen und aufzulösen, müssen Sie ein Array von Adressen an die Klasse übergeben, die die Suche selbst abwickelt und ein Versprechen zurückgibt, das Wenn aufgelöst, wird ein Array zurückgegeben, das alle aufgelösten (und nicht aufgelösten) Adressen enthält.
Beispiel:
var myAmazingGeo = new Geolocalizer();
var locations = ["Italy","California","Dragons are thugs...","China","Georgia"];
myAmazingGeo.Localize(locations).then(function(res){
console.log(res);
});
Konsolenausgabe:
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
Zurückgegebenes Objekt:
Die ganze Magie passiert hier:
(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);
Grundsätzlich durchläuft es jedes Element mit einer Verzögerung von 750 Millisekunden zwischen jedem Element, daher wird alle 750 Millisekunden eine Adresse gesteuert.
Ich habe einige weitere Tests durchgeführt und festgestellt, dass ich selbst bei 700 Millisekunden manchmal den Fehler QUERY_LIMIT bekam, während ich bei 750 überhaupt kein Problem hatte.
In jedem Fall können Sie die oben genannten 750 bearbeiten, wenn Sie sich durch eine geringere Verzögerung sicher fühlen.
Hoffe das hilft jemandem in naher Zukunft;)