我在代码中使用Google地理编码。我必须对约50个地方进行地理编码,
但是Google不允许同时对多个地方进行地理编码,从而产生“OVER_QUERY_LIMIT”错误。
因此,当我超出配额时,我想将地理编码延迟几秒钟。
我有一个函数geocode()
,它返回一个promise
。当我超出配额时,我想递归调用自己。
这是我不工作的代码:
function geocodeAll(addresses)
{
for (addr in addresses)
{
geocode(addresses[addr])
.then(
function(coord)
{/* I don't always get here */}
)
}
}
function geocode(address)
{
var deferred = Q.defer();
geocoder.geocode(address, function ( err, geoData )
{
if (err)
{ deferred.reject(err);}
else
{
if (geoData.status=="OVER_QUERY_LIMIT" )
{ // doh! quota exceeded, delay the promise
setTimeout(function()
{geocode(address)
.then(
function(coord)
{deferred.resolve(coord);}
);
}, 1000);
}
else
{ // everything ok
var coord = {'lat':geoData.lat, 'lng':geoData.lng};
deferred.resolve(coord);
}
}
});
return deferred.promise;
}
UPDATE [已解决]
实际上代码是正确的。我有一个与延迟无关的uncaughtException。使用
Q.all([..]).then().catch()
我找到了 最佳答案
您的代码似乎可以正常工作。我在您的代码中看到的唯一问题是您使用的lat
和lng
超出范围。但是您可能已经正确地编写了代码,而只是不包括代码。我怀疑您可能错误地使用了两者。应该是geoData.lat
和geoData.lng
吗?var coord = { 'lat': geoData.lat, 'lng': geoData.lng };
Plnkr
编辑
我认为您的问题可能与geocodeAll
函数的实现有关。
function geocodeAll(addresses)
{
for (addr in addresses)
{
geocode(addresses[addr]) /* This seems error prone to me! Try keeping track of all your promises.*/
.then(
function(coord)
{/*You only get here if there was no error returned from the geo request to the api. */}
)
}
}
使用
Q.all
跟踪,function geocodeAll(addresses) {
var promises = addresses.map(geocode);
for (addr in addresses) {
promises.push(
geocode(addresses[addr])
.catch(console.log.bind(console)) /* handle your error however you see fit*/
);
}
return Q.all(promises).then(function(results) {
var firstCord = results[0];
var secondCord = results[1];
//etc...
});
}
或者,您也可以使用
Q.allSettled
处理成功/失败function geocodeAll(addresses) {
var promises = addresses.map(geocode);
return Q.allSettled(promises).then(function (results) {
var success = [], fail = [];
results.forEach(function (result) {
if (result.state === "fulfilled") {
success.push(result.value);
} else {
fail.push(result.reason);
}
});
return { coords: success, errors: fail };
});
}
});