web-dev-qa-db-fra.com

Renvoie la valeur de la fonction imbriquée en Javascript

J'ai une fonction qui est configurée comme suit

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

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

Pour ma logique, cette alerte devrait retourner 'foo', mais à la place elle retourne non définie. Qu'est-ce que je fais mal?

UPDATE : Voici mon code actuel (c'est une fonction de géocodage inversé avec l'API Google)

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;
    });   
   }
54
Chris Armstrong

vous devez appeler une fonction avant qu'elle ne puisse retourner quoi que ce soit.

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

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

Ou:

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

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

pour votre code réel. Le retour doit être à l'extérieur, dans la fonction principale. Le rappel est appelé quelque part dans la méthode getLocations et donc sa valeur de retour n'est pas reçue dans votre fonction principale.

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
   }
60
z33m

Droite. La fonction que vous transmettez à getLocations () ne sera pas appelée tant que les données ne seront pas disponibles, donc retourner "country" avant qu'elles ne soient définies ne vous aidera pas.

Pour ce faire, vous devez faire en sorte que la fonction que vous transmettez à geocoder.getLocations () fasse ce que vous voulez faire avec les valeurs renvoyées.

Quelque chose comme ça:

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
  }
}

Si vous souhaitez faire quelque chose de différent chaque fois que vous obtenez l'emplacement, passez la fonction en tant que paramètre supplémentaire à 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);

Si cela semble un peu désordonné, vous pouvez jeter un œil à quelque chose comme la fonction différée dans Dojo, ce qui rend le chaînage entre les fonctions un peu plus clair.

3
Mark Bessey

Juste pour info, Geocoder est asynchrone donc la réponse acceptée alors que logique ne fonctionne pas vraiment dans ce cas. Je préférerais avoir un objet extérieur qui fasse office de mise à jour.

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);
                }
        }
    });
};
1
efwjames