Return value from function and place into variable in separate function

I'm trying to obtain the value of var newtotal from a separate function, which then passes the value on to a PHP script via Ajax.

Here's my code: `

function customerCost(){

        var newtotal;

        var start = document.getElementById('source').value;
        var end = document.getElementById('destination').value;
        var via = document.getElementById('via').value;

        if(via != ""){
        var waypts = [];

        waypts.push({
            location:via,
            stopover:false});

        var newrequest = {
          origin: start,
          destination: end,
          waypoints: waypts,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
        directionsService.route(newrequest, function(newresponse, newstatus) {
          if (newstatus == google.maps.DirectionsStatus.OK) {

            var newtotal = 0;
            var mynewroute = newresponse.routes[0];
             for (i = 0; i < mynewroute.legs.length; i++) {
                 newtotal += mynewroute.legs[i].distance.value;
                }
                            return newtotal;
            }

        });

        }else{

            var newrequest = {
          origin: start,
          destination: end,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
        directionsService.route(newrequest, function(newresponse, newstatus) {
          if (newstatus == google.maps.DirectionsStatus.OK) {

            var newtotal = 0;
            var mynewroute = newresponse.routes[0];
             for (i = 0; i < mynewroute.legs.length; i++) {
                 newtotal += mynewroute.legs[i].distance.value;
                }
                return newtotal;
            }

        });

        }



    }

I am then calling the value from within a separate function with the following:

customertotal = customerCost();

I am only getting an "undefined" error. However if I replace the return newtotal; for alert(newtotal); then it outputs the correct value.

Where am I going wrong?

Upvotes: 1

Views: 72

Answers (2)

shawnzhu
shawnzhu

Reputation: 7585

you should use callback function to work with variables inside asynchronous functions.

You can add a callback function as parameter:

customerCost(callback){

  // your original code
}

Then replace all line like return newtotal by callback(newtotal);

Then invoke function customerCost like:

customerCost(function(customertotal){
  // work with customertotal
});

Upvotes: 1

jfriend00
jfriend00

Reputation: 707198

The directionsService.route() call is asynchronous. That means that when you call it, it only starts the operation and your customerCost() function continues and finishes long before the .route() ajax call has finished and called its callback.

You are trying to program in a synchronous fashion with an asynchronous operation. You can't do that. Your customerCost() function call cannot return the newtotal value because it isn't known yet at the time that function returns.

Instead, you need to learn how to program in an asynchronous way. Any code that needs the newtotal value needs to either be in the callback where that value is available or you can call a function from there and pass it the newtotal value.

A typical way to develop something like this might be with your own callback:

function customerCost(cb){

        var newtotal;

        var start = document.getElementById('source').value;
        var end = document.getElementById('destination').value;
        var via = document.getElementById('via').value;

        if(via != ""){
        var waypts = [];

        waypts.push({
            location:via,
            stopover:false});

        var newrequest = {
          origin: start,
          destination: end,
          waypoints: waypts,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
        directionsService.route(newrequest, function(newresponse, newstatus) {
          if (newstatus == google.maps.DirectionsStatus.OK) {

            var newtotal = 0;
            var mynewroute = newresponse.routes[0];
             for (i = 0; i < mynewroute.legs.length; i++) {
                 newtotal += mynewroute.legs[i].distance.value;
              }
              // call the callback and pass it the newtotal
              cb(newtotal);
            }

        });

        }else{

            var newrequest = {
          origin: start,
          destination: end,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
        directionsService.route(newrequest, function(newresponse, newstatus) {
          if (newstatus == google.maps.DirectionsStatus.OK) {

            var newtotal = 0;
            var mynewroute = newresponse.routes[0];
             for (i = 0; i < mynewroute.legs.length; i++) {
                 newtotal += mynewroute.legs[i].distance.value;
                }
                // call the callback and pass it the newtotal
                cb(newtotal);
            }

        });

    }
}


// call the asynchronous cost function and process the result
// in a callback function
customerCost(function(newtotal) {
    // the newtotal value is available here
});

Upvotes: 2

Related Questions