0

I have a javascript code like below to calculate the total distance between n markers.

var distance = 0;
function updateTimeAndDistance(timeAndPath) {
    realtracPath = timeAndPath.path;
    getDistance();
   console.log("calculated distance : " + distance);
}

function getDistance() {

    for ( var i = 0; i < realtracPath.length - 1 ; i++) {
        var startPos = new google.maps.LatLng(realtracPath[i].lat, realtracPath[i].lng);
        var endPos = new google.maps.LatLng(realtracPath[i+1].lat, realtracPath[i+1].lng);
        var request = {
            origin : startPos,
            destination : endPos,
            travelMode : google.maps.TravelMode.DRIVING
        };
        directionsService.route(request, function(response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                distance += response.routes[0].legs[0].distance.value;
            }
        });


    }
}

but I am worried that, will there be any inconsistency in the value of the distance calculated as the distance is calculated asynchronously.

EDIT: every time I run this, I am getting distance as zero. I am not understanding why, though I have used the global distance variable.

Thanks.

GuruKulki
  • 25,776
  • 50
  • 140
  • 201
  • Your variable realtrackPath does not exist on the global scope. I.e, my guess is that your loop is never entered. Try adding `var realtracPath;` to the top of your code. Note: it is probably better to be passing these variables around rather than leaving them outside the scope of your functions. – Joe Jun 30 '14 at 15:41
  • 1
    Looks like a duplicate of [How to return the response from an Ajax call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – apsillers Jun 30 '14 at 15:43
  • @ joe, all the variables are defined as per the scope. Sorry for not uploading the whole code. – GuruKulki Jun 30 '14 at 15:44
  • @Joe This is probably a timing issue, not a scope issue (i.e., `console.log` runs chronologically before the `directionsService.route` callback function). – apsillers Jun 30 '14 at 15:46
  • @apsillers, Yeah it is similar to the question you mentioned, but I am not getting any clue how to to use the answer provided there in my case. – GuruKulki Jun 30 '14 at 15:50
  • cant you add a callback to the getDistance function `getDistance(cb)` and then call `cb()` after you have added the response to the `distance` variable? Then you should just call `getDistance(function(){ console.log(distance) })` – Joe Jun 30 '14 at 15:50
  • @joe, I am not aware how to do that, as this I working on javascripts recently. – GuruKulki Jun 30 '14 at 15:52
  • Added example code as an answer – Joe Jun 30 '14 at 15:54
  • @joe, It is working now, thank you very much. Now I understand how the callback feature works in javascript. – GuruKulki Jun 30 '14 at 16:02
  • @joe, but there is one small prob, the callback gets called each time the loop runs, cant we avoid this to make it run only once? – GuruKulki Jun 30 '14 at 16:07
  • Updated answer to include a latch. Should only callback when all loops have completed. Glad you get callbacks now. I must admit that coming from a java background the idea of passing functions took me a while to get my head around. It can be really powerful once you get to grips with it! – Joe Jun 30 '14 at 16:41

1 Answers1

1

Try introducing an async callback function like so;

var distance = 0;
function updateTimeAndDistance(timeAndPath) {
    realtracPath = timeAndPath.path;
    getDistance(function(){
        console.log("calculated distance : " + distance);
    });

}

function getDistance(cb) {
var latch = realtrackPath.length;
for ( var i = 0; i < realtracPath.length - 1 ; i++) {
    var startPos = new google.maps.LatLng(realtracPath[i].lat, realtracPath[i].lng);
    var endPos = new google.maps.LatLng(realtracPath[i+1].lat, realtracPath[i+1].lng);
    var request = {
        origin : startPos,
        destination : endPos,
        travelMode : google.maps.TravelMode.DRIVING
    };
    directionsService.route(request, function(response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            distance += response.routes[0].legs[0].distance.value;
            latch--
            if (latch==0){
               cb()
            }                
        }
    });


}

}

Note: If the status does not come back as OK nothing will happen. It can be quite handy to have callbacks with function signatures that pass booleans indicating errors etc.

Joe
  • 1,455
  • 2
  • 19
  • 36