理解异步javascript(谷歌地图)
我下面的答案有一个工作代码示例和一个解释理解异步javascript(谷歌地图),javascript,google-maps,asynchronous,callback,Javascript,Google Maps,Asynchronous,Callback,我下面的答案有一个工作代码示例和一个解释 我正试图通过在GoogleMapsAPI的帮助下创建一个旅行推销员算法来了解异步编程 以下是它应该如何工作: 我们有一个地址字符串列表地址 对于地址[i]和[j]的每个组合,我们使用谷歌计算距离 directionsService,我们将其存储在Javascript对象(distanceTable)中 tspSolver应该在我们完成所有距离后运行(尚未实现) 下面是我的天真代码。正如您所看到的,有几个问题都与回调有关: 我将directionResu
我正试图通过在GoogleMapsAPI的帮助下创建一个旅行推销员算法来了解异步编程 以下是它应该如何工作:
地址
distanceTable
)中directionResults
作为回调传递给directionservice。它正确地计算了距离,但由于我不再在循环中构造距离表,因此无法正确存储结果。我注释掉了应该存储它的部分,但这显然只在循环内部起作用
我通过我的tspSolver
作为alldistance
的回调。但是我注意到,它在距离由directionResults
计算之前执行。我的猜测是,我必须对回调进行某种形式的嵌套
谁能帮我弄明白这一点
gMap.directionsService = new google.maps.DirectionsService();
var addresses = ['Dam, Amsterdam','Spui, Amsterdam','Middenweg, Amsterdam'];
var distanceTable = {};
//all combinations of addresses with distances, for use in TSP algorithm
//{
// addressA {
// addressB: 2000
// addressC: 2500
// }
// addressB {
// addressC: 1800
// }
function tspSolver(distanceTable) {
console.log('Distances are there, now for some clever TSP algorithm')
//this should only be executed after the distances are returned.
}
function allDistances(addresses, callback) {
for(var i=0; i<addresses.length; ++i) {
distanceTable[addresses[i]] = {};
for(var j=i+1; j<addresses.length; ++j) {
// Compose request for every pair of addresses (one way)
var request = {
origin: addresses[i],
destination: addresses[j],
travelMode: 'DRIVING'
};
console.log(request);
gMap.directionsService.route(request, directionResults);
}
}
callback(distanceTable)
}
function directionResults(result, status) {
console.log("Receiving request for route");
console.log(result);
if (status == google.maps.DirectionsStatus.OK) {
var totalDistance = 0;
var legs = result.routes[0].legs;
for(var i=0; i<legs.length; ++i) {
totalDistance += legs[i].distance.value;
}
console.log(totalDistance);
// I really want to add it to the distanceTable...
//distanceTable[addresses[i]][addresses[j]] = totalDistance;
}
}
//call function to start solving
function executeTSP() {
allDistances(addresses, tspSolver);
}
gMap.directionsService=new google.maps.directionsService();
var地址=['Dam,阿姆斯特丹','Spui,阿姆斯特丹','Middenweg,阿姆斯特丹'];
var距离表={};
//带距离的所有地址组合,用于TSP算法
//{
//地址{
//地址B:2000
//地址C:2500
// }
//地址B{
//地址C:1800
// }
函数tspSolver(距离表){
log('距离在那里,现在是一些聪明的TSP算法')
//这只能在返回距离后执行。
}
函数所有距离(地址、回调){
对于(var i=0;i我假设您需要通过请求传递回调
回调是在异步编程时继续执行的方式
伪示例:
function doAcync(callback)
{
//gets result
callback(result);
}
function one()
{
doAcync(two);
}
function two(result)
{
doAcync(three);
}
function three(result)
{
// continue with your live
}
我的第一个问题的解决方案是“循环中的闭包”。我用一个计数器(在我的例子中是两个计数器)跟踪我的循环。当异步函数/闭包执行时,循环已经完成
这将挫败从闭包中访问循环计数器的所有尝试:您将始终获得最大数量
我选择的解决方案是将闭包包装在另一个函数中:一个所谓的“匿名包装器”。这个包装器包含一个不受循环影响的引用
以下是一些更好的解释:
在这里:
为了解决第二个问题(执行顺序),我求助于在回调中进行回调。一些公认丑陋的代码跟踪回调只在最后一次迭代中被调用。我确信有更优雅的方法来处理这一问题,但目前它可以工作:
var directionsService;
function initialize() {
directionsService = new google.maps.DirectionsService();
}
var addresses = ['Dam, Amsterdam','Spui, Amsterdam','Middenweg, Amsterdam'];
var distanceTable = {};
//all combinations of addresses with distances, for use in TSP algorithm
//{
// addressA {
// addressB: 2000
// addressC: 2500
// }
// addressB {
// addressC: 1800
// }
function tspSolver(distances) {
//this function is called as a callback from allDistances
for(var i=0; i<addresses.length; ++i) {
for(var j=i+1; j<addresses.length; ++j) {
console.log(addresses[i]+' to '+addresses[j]+': '+distances[addresses[i]][addresses[j]])
}
}
}
function allDistances(addresses, callback) {
for(var i=0; i<addresses.length; ++i) {
distanceTable[addresses[i]] = {};
for(var j=i+1; j<addresses.length; ++j) {
var request = {
origin: addresses[i],
destination: addresses[j],
travelMode: 'DRIVING'
};
console.log(request);
//anonymous wrapper around closure to preserve the loop counters: i,j -> e,f
(function(e,f) {directionsService.route(request, function(result,status) {
if (status == google.maps.DirectionsStatus.OK) {
//calculate totalDistance as sum of the legs and store the result
var totalDistance = 0;
var legs = result.routes[0].legs;
for(var x=0; x<legs.length; ++x) {
totalDistance += legs[x].distance.value;
}
distanceTable[addresses[e]][addresses[f]] = totalDistance;
}
//trigger the callback on the last iteration only
if (e+2 == addresses.length)
{
callback(distanceTable)
}
});
})(i,j);
//end of wrapper
}
}
}
function executeTSP(){
allDistances(addresses, tspSolver)
}
var方向服务;
函数初始化(){
directionsService=new google.maps.directionsService();
}
var地址=['Dam,阿姆斯特丹','Spui,阿姆斯特丹','Middenweg,阿姆斯特丹'];
var距离表={};
//带距离的所有地址组合,用于TSP算法
//{
//地址{
//地址B:2000
//地址C:2500
// }
//地址B{
//地址C:1800
// }
函数tspSolver(距离){
//此函数作为来自allDistances的回调调用
对于(var i=0;iSo传递给函数2和函数3的“结果”是什么?抱歉,但我在理解这一点时遇到了一些困难。大多数ppl一开始都不担心。结果是从一个不连续的调用中检索到的,这是一种惯例,即如果传递回调,并且传递回调的函数具有返回值e、 然后用返回值调用回调函数。我认为您的模式将帮助我解决第二个问题(执行顺序).我不相信将结果写入距离表会对我有帮助…我用工作代码添加了另一个答案。我认为这并不漂亮,但它完成了工作。我必须承认我没有使用你的模式,但感谢你的帮助。