Google 使用 javascript 在循环中对多个地址进行地理编码,我怎么知道一切何时完成?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9052393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google geocoding multiple addresses in a loop with javascript, how do I know when everything is done?
提问by user985219
I've got a form that asks for a list of locations (not a lot, normally only 3 or 4 but that number is dynamic). When the form is submitted, I have to parse the data, use Google geocoding to get the locations, and then draw a line connecting the points in order. I have the parsing working, but I'm stuck on the geocoding part, mostly because of the asynchronous nature of it. Assume my address strings are stored in the array 'addresses', this is how far I've gotten:
我有一个表格要求提供位置列表(不是很多,通常只有 3 或 4 个,但该数字是动态的)。提交表单时,我必须解析数据,使用谷歌地理编码获取位置,然后按顺序绘制连接点的线。我有解析工作,但我被困在地理编码部分,主要是因为它的异步性质。假设我的地址字符串存储在数组“addresses”中,这是我得到的程度:
function someFunction(addresses) {
var coords = [];
for(var i = 0; i < addresses.length; i++) {
currAddress = addresses[i];
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({'address':currAddress}, function (results, status)
if (status == google.maps.GeocoderStatus.OK) {
coords.push(results[0].geometry.location);
}
else {
throw('No results found: ' + status);
}
});
}
}
// Initially I tried to work with the data here, but it wasn't all present yet.
}
Drawing the line is easy enough, I've done that before when users provided geographic lat/lng coordinates. My problem is, because the coordinates are only added in the callback, how do I know when it's done? I can't just dump that into a function and put in the callback because I need to wait until all the coordinates have been processed.
画线很容易,我以前在用户提供地理纬度/经度坐标时已经这样做了。我的问题是,因为坐标只在回调中添加,我怎么知道它什么时候完成?我不能只是将它转储到一个函数中并放入回调中,因为我需要等到所有坐标都处理完毕。
I also read about someone who had issues with results not coming back in order but I didn't understand the provided response. If someone has an answer that can help me with my specific issue and ensure the results come back in order, I would greatly appreciate.
我还读到有人遇到结果无法按顺序返回的问题,但我不明白所提供的回复。如果有人的答案可以帮助我解决我的具体问题并确保结果按顺序返回,我将不胜感激。
NB: I hand-bombed that code, so there may be typos. My actual code thus far "works", I just don't know who to move from what I have to doing something once all addresses are processed. Also, this is currently being developed as an internal application for testing. Once testing is finished, it will comply fully with Google's TOS. This means I don't have a page I can link to. The entire application is also over 2,000 lines of code and contains some proprietary company information at this moment which will eventually be phased out, so pasting the entire thing or sending it out isn't feasible. I hope that doesn't pose too big a problem.
注意:我手工炸了那个代码,所以可能会有错别字。到目前为止,我的实际代码“有效”,我只是不知道在处理完所有地址后谁应该从我必须做的事情转移到做某事。此外,目前正在开发作为内部测试应用程序。测试完成后,将完全符合 Google 的 TOS。这意味着我没有可以链接到的页面。整个应用程序也有2000多行代码,其中包含一些公司专有信息,这些信息目前最终将被淘汰,因此将整个内容粘贴或发送出去是不可行的。我希望这不会造成太大问题。
回答by jwchang
function someFunction(addresses, callback) {
var coords = [];
for(var i = 0; i < addresses.length; i++) {
currAddress = addresses[i];
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({'address':currAddress}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
coords.push(results[0].geometry.location);
if(coords.length == addresses.length) {
if( typeof callback == 'function' ) {
callback();
}
}
}
else {
throw('No results found: ' + status);
}
});
}
}
}
}
//Usage
someFunction(addresses, function() {
// Do something after getting done with Geocoding of multiple addresses
});
Use of Callback function is amazing
回调函数的使用很神奇
回答by Julian D.
You could check if all calls have been finished by comparing the number of results to the number of addresses:
您可以通过将结果数与地址数进行比较来检查是否所有调用都已完成:
function someFunction(addresses) {
var currAddress, coords = [];
for (var i = 0; i < addresses.length; i++) {
currAddress = addresses[i];
var geocoder = new google.maps.Geocoder();
if (geocoder) {
geocoder.geocode({'address':currAddress}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
coords.push(results[0].geometry.location);
// Check if all calls have been processed
if (coords.length == addresses.length) {
someOtherFunction(coords);
}
}
...
});
}
}
}
function someOtherFunction(coords) {
// Geocoding has been done for all addresses
...
}
回答by Vadim Gremyachev
If you are utilizing libraries such as jQuery
, you could take advantage of Deferred Objectto perform a chainable requests via geocoder.geocode
function.
如果您正在使用诸如 之类的库jQuery
,则可以利用延迟对象通过geocoder.geocode
函数执行可链接的请求。
Example
例子
function initMap() {
var geocoder = new google.maps.Geocoder();
var addreses = [
{ "lat": 60.173890, "lng": 24.941025 },
{ "lat": 60.461608, "lng": 22.266598 },
{ "lat": 61.498714, "lng": 23.760940 }
];
var deferreds = getGeocodeAddressDeferred(geocoder,addreses);
$.when.apply($, deferreds).done(function (locations) {
//print results
$.each(arguments, function (i, data) {
$("div#result").append(data + "<br/>");
});
});
}
function getGeocodeAddressDeferred(geocoder, addreses) {
var deferreds = [];
$.each(addreses, function (i,address) {
deferreds.push(geocodeAddress(geocoder, address));
});
return deferreds;
}
function geocodeAddress(geocoder, latLng) {
var deferred = $.Deferred();
geocoder.geocode({ 'location': latLng }, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
deferred.resolve(results[0].formatted_address);
}
});
return deferred.promise();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
async defer></script>
<div id="result"/>
回答by sista_melody
This is quite old but there's a problem of closure in the given answers so final result has same lat,long for all addresses.
这已经很老了,但是在给定的答案中存在关闭问题,因此最终结果对于所有地址具有相同的纬度和长度。
It's better to loop through all addresses using addresses.forEachso that each geocoded address is contained and this should work fine provided target browsers are modern. Otherwise, you have to define an outside function to tackle the javascript infamous loop issue. Here is forEach solution for an array of addresses:
最好使用addresses.forEach遍历所有地址,以便包含每个经过地理编码的地址,如果目标浏览器是现代的,这应该可以正常工作。否则,您必须定义一个外部函数来解决javascript 臭名昭著的循环问题。这是地址数组的 forEach 解决方案:
var getLatLng = function(addresses, callback) {
var coords = [];
addresses.forEach(function(address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
coords.push([lat, lng]);
// all addresses have been processed
if (coords.length === addresses.length)
callback(coords);
}
});
});
}
getLatLng(allAddresses, function (results) {
console.log("received all addresses:", results);
});