Wait for Loop to finish before passing the value i

2019-05-23 23:00发布

I don't use javascript much so I am not that familiar with callbacks and responses. I am using google maps to map out distance between point A and point X,Y,Z. The catch is, I want to use javascript to determine which of the points X,Y,Z is closest to A and them map out the directions between them.

My code is working. I can figure out the shortest distance out all the 3 destinations but I am stuck with this stupid for look.

You see, Google uses async callbacks to provide data to the browser and if I run a for loop to check all the 3 destinations 1 by 1, I get incorrect results.

Here is the code:

var maxDistance = 99999999999;
var destn;
for (var i = 0; i < locations.length; i++) {
  var thisDistance = 0;
  var start = origin;
  var end = locations[i];
  var request = {
    origin: start,
    destination: end,
    travelMode: google.maps.DirectionsTravelMode.DRIVING
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      thisDistance = response.routes[0].legs[0].distance.value;
      if (thisDistance < maxDistance) {
        destn = response.routes[0].legs[0].end_address;
        maxDistance = thisDistance;
      }
    } else {
      document.getElementById("addressNotFound").style.display = 'block';
    }
  });
}
calcShortestRoute(origin, destn);

So obviously when I call this function, the value of destn comes up as undefined since the loop finishes and the google handler hasnt received the data yet. If I call the function 1 more time, I get the destn value that was received from the previous callback (which gave undefined before).

Someone please tell me how I can fix this.

2条回答
乱世女痞
2楼-- · 2019-05-23 23:50

You need to wait until all three Google responses have been returned. A simple solution is: move you distance calculation function call into the anonymous function at the end, and then calc the distances only if all responses have returned:

        // global count variable
        var callbackCount = 0;

        for (var i = 0; i<locations.length; i++) {
            var thisDistance=0;
            var start = origin;
            var end = locations[i];
            var request = {
                origin:start,
                destination:end,
                travelMode: google.maps.DirectionsTravelMode.DRIVING
            };
            directionsService.route(request, function(response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    thisDistance = response.routes[0].legs[0].distance.value;
                    if (thisDistance < maxDistance) {
                        destn = response.routes[0].legs[0].end_address;
                        maxDistance = thisDistance;
                    }                            
                }
                else {
                    document.getElementById("addressNotFound").style.display = 'block';
                }

                // move this to here, and pass in number of locations
                calcShortestRoute(origin, destn, locations.length);
            });



        }

then calcShortestRoute looks like:

function calcShortestRoute(origin, destn, locationCount) {

  // increment callback count
  callbackCount++;

  if (callbackCount == locationCount) {   // all responses have returned


     // do your distance checking      
     ....

   }
}
查看更多
虎瘦雄心在
3楼-- · 2019-05-23 23:53

You won't have a value in destn when you exit the for loop because it is set asynchronously after you receive your results from directionsService.route(). Instead, you'll need to keep track of how many requests have returned, and call your function from within the response callback after you've received all of the responses:

... // your code
var responseCount = 0;
for (var i = 0; i < locations.length; i++) {
    ... // your code
    directionsService.route(request, function(response, status) {
        ... // your code
        if (++responseCount == locations.length) {
            calcShortestRoute(origin, destn);
        }
    });
}

Edit: I re-read your question and think I understand better what your code is doing. This answer should be more accurate (and more concise to boot!).

查看更多
登录 后发表回答