Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解异步javascript(谷歌地图)_Javascript_Google Maps_Asynchronous_Callback - Fatal编程技术网

理解异步javascript(谷歌地图)

理解异步javascript(谷歌地图),javascript,google-maps,asynchronous,callback,Javascript,Google Maps,Asynchronous,Callback,我下面的答案有一个工作代码示例和一个解释 我正试图通过在GoogleMapsAPI的帮助下创建一个旅行推销员算法来了解异步编程 以下是它应该如何工作: 我们有一个地址字符串列表地址 对于地址[i]和[j]的每个组合,我们使用谷歌计算距离 directionsService,我们将其存储在Javascript对象(distanceTable)中 tspSolver应该在我们完成所有距离后运行(尚未实现) 下面是我的天真代码。正如您所看到的,有几个问题都与回调有关: 我将directionResu

我下面的答案有一个工作代码示例和一个解释


我正试图通过在GoogleMapsAPI的帮助下创建一个旅行推销员算法来了解异步编程

以下是它应该如何工作:

  • 我们有一个地址字符串列表
    地址
  • 对于地址[i]和[j]的每个组合,我们使用谷歌计算距离 directionsService,我们将其存储在Javascript对象(
    distanceTable
    )中
  • tspSolver应该在我们完成所有距离后运行(尚未实现)
  • 下面是我的天真代码。正如您所看到的,有几个问题都与回调有关:

    我将
    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、 然后用返回值调用回调函数。我认为您的模式将帮助我解决第二个问题(执行顺序).我不相信将结果写入距离表会对我有帮助…我用工作代码添加了另一个答案。我认为这并不漂亮,但它完成了工作。我必须承认我没有使用你的模式,但感谢你的帮助。