0

I'm trying to use the Google Maps v3 API to calculate the distance between several postcodes. I have a starting postcode and 5 destination postcodes, so it’s a case of locating the nearest destination from the starting point. I'm passing the postcode info to the web page via query string on the URL.

Example of the 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

So, here's the magic bit, for which most of the part works. Ignore the numerous alerts, they're just for debugging. The bit that doesn't seem to work as I need it to is the directionsService.route part highlighted below.

The problem I'm having is when calcRoute() is called, as you can see most of the function is wrapped inside a for loop so I can cycle through the function for each postcode in the queryParms array, but the directionsService.route method isn't executed as part of the rest of the function; the for loop seems to go through the rest of the function the appropriate number of times until getNearest() is called, and then the directionsService.route method is called afterwards the same number of times as the for loop dictated, so it's as if the function is split into two and the for loop goes through each part separately. Does anyone know how I can resolve this problem?

<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>
10
  • 2
    Welsome to stackoverflow. Please learn to format your posts! Commented Oct 22, 2013 at 14:14
  • 2
    Perhaps misspelling a comment criticizing semantics wasn't the best idea. @epascarello Commented Oct 22, 2013 at 14:17
  • 1
    You should try in terms of learning how to ask a question. Click on edit. You can see how the modified code is made to look different. Learn the syntax from each question you visit by clicking on edit. Just check out how the different symbols work to improve the formatting of the question. Commented Oct 22, 2013 at 14:25
  • 1
    This seems to confirm that your call to the Google API is asynchronous: Accessing the Directions service is asynchronous, since the Google Maps API needs to make a call to an external server. For that reason, you need to pass a callback method to execute upon completion of the request. Commented Oct 22, 2013 at 14:27
  • 1
    @Rajesh - thank you, i will work on the formatting of my questions, and the URL doesn't really have spaces, it's my bad formatting Commented Oct 22, 2013 at 14:35

2 Answers 2

1

The call to directionsService.route issues an AJAX call, which is why you have to pass a callback function. However, since you're issuing the call inside a for loop and attempting to use the counter variable i inside the callback function's body, you'll run into issues because i won't retain the value for that iteration when the callback function executes; if all of the AJAX requests complete after the loop (which is likely) then i will be the value for the last iteration of the loop in each of them.

You'll need to create a closure to preserve its value, like so:

(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);
Sign up to request clarification or add additional context in comments.

Comments

1

The directionsService.route method is asynchronous, hence the second parameter is a function which will execute when the AJAX call is complete.

But you call GetNearest() outside of this callback, so when the for loop is at it's last iteration, GetNearest() will be called before all the callbacks have gotten a chance to execute.

Try moving the if statement if (j == queryParms.length) {...} inside the callback.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.