开发者

Returning values in Javascript

I have a (hopefully quite simple) Javascript problem. I've search but found nothing that is really relevant to the problem.

Basically I have a function (addToGlobe) that calls two other functions (codeAddressLat and codeAddressLng) as it runs. The two called functions should both return a float value to the first function, which then uses them. The subfunctions definitely work correctly - I did a print statement to check that the "numfinal" variable in each has a value, and it does.

However, when I add print statements to the calling function (as commented in the code), it returns 'undefined'. Therefore, the problem seems to be when the numfinal value is returned.

Thanks :)

function addToGlobe(uname, uid, pmcity) {
    // Get lat & long of city
    var pmlat = codeAddressLat(pmcity);
    var pmlong = codeAddressLng(pmcity);

    log(pmlat);   // P开发者_如何转开发ROBLEM! Prints 'undefined'
    log(pmlong);  // PROBLEM! Prints 'undefined'

    // Rest of function removed to keep it simple
}

function codeAddressLat(inputcity) {
    geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(-34.397, 150.644);

    geocoder.geocode( { 'address': inputcity}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          var llsplit = new Array();

          bkresult = String(results[0].geometry.location);
          bkresult = bkresult.replace(/[\(\)]/g, "");
          llsplit = bkresult.split(',');

          numfinal = parseFloat(llsplit[0]);
          return numfinal;

      } else {
        log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
      }
    });
 }

  function codeAddressLng(inputcity) {
        // Basically the same function as above. Removed for simplicity
     }


codeAddressLat is not actually returning anything. The anonymous function it passes to geocoder.geocode is.

Since geocoder.geocode is running asynchronously, codeAddressLat can't wait around for its answer. So codeAddressLat really can't return anything of value. Instead codeAddressLat needs to become asynchronous too. This is a common pattern in JavaScript.

function addToGlobe(uname, uid, pmcity) {
     codeAddressLat(pmcity, function(pmlat) {
        // do something with pmlat
    });

    ...
}

function codeAddressLat(inputcity, callback) {
    geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(-34.397, 150.644);

    geocoder.geocode( { 'address': inputcity}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          var llsplit = new Array();

          bkresult = String(results[0].geometry.location);
          bkresult = bkresult.replace(/[\(\)]/g, "");
          llsplit = bkresult.split(',');

          numfinal = parseFloat(llsplit[0]);

          // instead of returning, call the callback with the result
          callback(numfinal);

      } else {
        log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
      }
    });
}


You don't have a return statement in codeAddressLat, you have one inside a callback function defined inside codeAddressLat.


Your function codeAddressLat is not actually returning a value but calling function that you pass a callback function which is returning a value. You need to wait until the geocode operation is complete to retrieve the value of numfinal.


Your function codeAddressLat is not returning any value at all hence you are getting undefined as output.


The geocode request in the codeAddressLat method call and will not return the value to the caller. Your return is of a different scope.


Does this work?

function codeAddressLat(inputcity) {
    geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(-34.397, 150.644);

    return geocoder.geocode( { 'address': inputcity}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
          var llsplit = new Array();

          bkresult = String(results[0].geometry.location);
          bkresult = bkresult.replace(/[\(\)]/g, "");
          llsplit = bkresult.split(',');

          numfinal = parseFloat(llsplit[0]);
          return numfinal;

      } else {
        log('<b><font color="#C40031">Geocode was not successful:</b> ' + status);
      }
    });
 }


That geocoder.geocode function looks like it is asynchronous. Your codeAddressLat and codeAddressLng functions returns void before the geocoder.geocode function has got data back from the server.

A way to get around it is to nest your calls to geocoder.geocode and use variable scoping so that when all the AJAX calls have returned you can call your addToGlobe function passing the two parameters you want.

Something like this:

codeAddressLatAndLong(pmcity);

function addToGlobe(pmlatlat, pmlatlong) {
    log(pmlat);   // PROBLEM! Prints 'undefined'
    log(pmlong);  // PROBLEM! Prints 'undefined'

    // Rest of function removed to keep it simple
}

function codeAddressLatAndLong(inputcity) {
    // stuff

    geocoder.geocode( { 'address': inputcity}, function(results, status) {
      // stuff goes here
      pmlat = parseFloat(llsplit[0]);
      geocoder.geocode({...}, function(results, status) {
         // more stuff
         pmlatlong = something;
         addToGlobe(pmlatlat, pmlatlong);
      });
    });
}

Welcome to the world of AJAX.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜