Return value from nested function in Javascript [duplicate]

I have a function that is set up as follows

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
}

var test = mainFunction();
alert(test);

To my logic, that alert should return 'foo', but instead it returns undefined. What am I doing wrong?

UPDATE: Here's my actual code (it's a function for reverse-geocoding with the Google API)

function reverseGeocode(latitude,longitude){
    var address = "";
    var country = "";
    var countrycode = "";
    var locality = "";

    var geocoder = new GClientGeocoder();
    var latlng = new GLatLng(latitude, longitude);

     return geocoder.getLocations(latlng, function(addresses) {
     address = addresses.Placemark[0].address;
     country = addresses.Placemark[0].AddressDetails.Country.CountryName;
     countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
     locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
     return country;
    });   
   }

Answers:

Answer

you have to call a function before it can return anything.

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
      return subFunction();
}

var test = mainFunction();
alert(test);

Or:

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
      return subFunction;
}

var test = mainFunction();
alert( test() );

for your actual code. The return should be outside, in the main function. The callback is called somewhere inside the getLocations method and hence its return value is not recieved inside your main function.

function reverseGeocode(latitude,longitude){
    var address = "";
    var country = "";
    var countrycode = "";
    var locality = "";

    var geocoder = new GClientGeocoder();
    var latlng = new GLatLng(latitude, longitude);

    geocoder.getLocations(latlng, function(addresses) {
     address = addresses.Placemark[0].address;
     country = addresses.Placemark[0].AddressDetails.Country.CountryName;
     countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
     locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
    });   
    return country
   }
Answer

Right. The function you pass to getLocations() won't get called until the data is available, so returning "country" before it's been set isn't going to help you.

The way you need to do this is to have the function that you pass to geocoder.getLocations() actually do whatever it is you wanted done with the returned values.

Something like this:

function reverseGeocode(latitude,longitude){
  var geocoder = new GClientGeocoder();
  var latlng = new GLatLng(latitude, longitude);

  geocoder.getLocations(latlng, function(addresses) {
    var address = addresses.Placemark[0].address;
    var country = addresses.Placemark[0].AddressDetails.Country.CountryName;
    var countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
    var locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
    do_something_with_address(address, country, countrycode, locality);
  });   
}

function do_something_with_address(address, country, countrycode, locality) {
  if (country==="USA") {
     alert("USA A-OK!"); // or whatever
  }
}

If you might want to do something different every time you get the location, then pass the function as an additional parameter to reverseGeocode:

function reverseGeocode(latitude,longitude, callback){
  // Function contents the same as above, then
  callback(address, country, countrycode, locality);
}
reverseGeocode(latitude, longitude, do_something_with_address);

If this looks a little messy, then you could take a look at something like the Deferred feature in Dojo, which makes the chaining between functions a little clearer.

Answer

Just FYI, Geocoder is asynchronous so the accepted answer while logical doesn't really work in this instance. I would prefer to have an outside object that acts as your updater.

var updater = {};

function geoCodeCity(goocoord) { 
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'latLng': goocoord
    }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            updater.currentLocation = results[1].formatted_address;
        } else {
            if (status == "ERROR") { 
                    console.log(status);
                }
        }
    });
};

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.