Javascript:for 循环似乎在执行代码之前拆分函数

Javascript: For loop seems to split function before executing code?

本文关键字:代码 拆分 函数 执行 for 循环 Javascript      更新时间:2023-09-26

我正在尝试使用Google Maps v3 API来计算几个邮政编码之间的距离。我有一个起始邮政编码和 5 个目的地邮政编码,因此可以从起点定位最近的目的地。我正在通过 URL 上的查询字符串将邮政编码信息传递到网页。

网址示例: /HTML/319976/try-map.html?siteloc=NG4 3AA United Kingdom&postcode1=E13 8HL United Kingdom&postcode2=LE5 0HJ United Kingdom&postcode3=G43 1PX United Kingdom&postcode4=DE22 3LR United Kingdom&postcode5=LS9 9NE United Kingdom

所以,这是魔术部分,大部分部分都适用于它。忽略众多警报,它们仅用于调试。似乎无法正常工作的位是下面突出显示的 directionsService .route 部分。

我遇到的问题是当调用calcRoute()时,正如你所看到的大部分函数都包装在一个for loop中,所以我可以为 queryParms 数组中的每个邮政编码循环访问函数,但 directionsService.route 方法不是作为函数其余部分的一部分执行的; for loop似乎通过函数的其余部分适当的次数,直到调用getNearest(), 然后调用 directionsService.route 方法的次数与 for 循环规定的次数相同,因此就好像函数被分成两部分,for loop分别遍历每个部分。有谁知道我该如何解决这个问题?

<script>
    var directionsDisplay;
    var directionsService = new google.maps.DirectionsService();
    var map;
    var locations = new Array();
    var queryParms = new Array();
    var start;
    var end;
    function initialize() {
    alert("initialize");
      directionsDisplay = new google.maps.DirectionsRenderer();
      var home = new google.maps.LatLng(52.966314, -1.08052);
      var mapOptions = {
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        center: home
      };
      map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
      directionsDisplay.setMap(map);
      getQueryVars();
    }
    function getQueryVars() {
    alert("getQueryVars");
      var pair;
      var query = window.location.search.substring(1); 
      var vars = query.split("&"); 
    alert("vars = " + vars);
      for (i=0;i<vars.length;i++) {
        pair = vars[i].split("=");
        if (pair[0] != "siteloc") { 
          queryParms.push(pair[1]);
    alert("queryParms = " + queryParms);
        } else {
            start = pair[1];
            alert("start = " + start);
            }
        }
      calcRoute(); 
    }
    function calcRoute() {
      for (j=0;j<queryParms.length;j++) {
        end = queryParms[j];
        alert("end (queryParms[j]) = " + end);
    //waypoints not used for this postcode distance search but left in for future use if needed
        var waypts = [];
        var checkboxArray = document.getElementById('waypoints');
        for (i = 0; i < checkboxArray.length; i++) {
          if (checkboxArray.options[i].selected == true) {
            waypts.push({
              location:checkboxArray[i].value,
              stopover:true});
        }
      }
    alert("creating request");
        request = {
        origin: start,
        destination: end,
        waypoints: waypts,
        optimizeWaypoints: true,
        travelMode: google.maps.TravelMode.DRIVING
        };
    alert(request);
        **directionsService.route(request, function(response, status) {
          if (status == google.maps.DirectionsStatus.OK) {
    alert("status ok");
            directionsDisplay.setDirections(response);
            var route = response.routes[0];
            numericOutput = route.legs[i].distance.text.replace(/ km/g,"");
    alert(numericOutput);
            locations.push({
              loc:end, 
              distance:numericOutput});
    alert(locations);
          }
        });**
      }
      if (j == queryParms.length) {
          getNearest();
      }
    }
    function getNearest()
    {
    alert("getNearest");
        locations.sort(function(a,b) {
        return a.val - b.val; });
        document.getElementById("output").value = locations[0];
    }
    google.maps.event.addDomListener(window, 'load', initialize);
</script>

directionsService.route的调用会发出 AJAX 调用,这就是您必须传递回调函数的原因。但是,由于您在 for 循环中发出调用尝试在回调函数的主体中使用i的计数器变量,因此会遇到问题,因为当回调函数执行时i不会保留该迭代的值;如果所有 AJAX 请求在循环后完成(很可能),则i将是每个请求中循环最后一次迭代的值。

您需要创建一个闭包来保留其值,如下所示:

(function(i) {
    directionsService.route(request, function (response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            alert("status ok");
            directionsDisplay.setDirections(response);
            var route = response.routes[0];
            numericOutput = route.legs[i].distance.text.replace(/ km/g, "");
            alert(numericOutput);
            locations.push({
                loc : end,
                distance : numericOutput
            });
            alert(locations);
        }
    });
})(i);

directionsService.route 方法是异步的,因此第二个参数是一个函数,它将在 AJAX 调用完成时执行。

但是你在此回调之外调用GetNearest(),所以当for循环处于最后一次迭代时,GetNearest()将在所有回调有机会执行之前被调用。

尝试将 if 语句if (j == queryParms.length) {...}移动到回调中。