2010-04-10 20 views
44

que tiene una función que está configurado de la siguiente maneravalor de retorno de la función anidada en Javascript

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

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

Para mi lógica, que alerta debe devolver 'foo', pero en su lugar se vuelve indefinida. ¿Qué estoy haciendo mal?

ACTUALIZACIÓN: Aquí está mi código real (que es una función inversa de geocodificación con la API de 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; 
    }); 
    } 
+4

recomiendo leer acerca de cómo Javascript Cierres de trabajo: http://jibbering.com/faq/faq_notes/closures.html#clClose – Bartek

Respuesta

54

usted tiene que llamar a una función antes de que pueda devolver nada.

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

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

O:

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

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

para su código real. El retorno debe estar afuera, en la función principal. La devolución de llamada se llama en algún lugar dentro del método getLocations y, por lo tanto, su valor de retorno no se recibe dentro de su función principal.

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

He actualizado mi pregunta con el código real. El problema que tengo es que estoy trabajando con la API de Google y, por lo tanto, una de sus funciones llama a mi subfunción. ¿Alguna idea de cómo lo solucionaría? –

+0

Gracias. El problema es que cuando simplemente pongo el país de retorno; vuelve "", porque generalmente no he recibido la información de Google lo suficientemente rápido. ¿Hay alguna manera de hacerlo esperar hasta que cambie el valor? –

+1

@chris, creo que la mejor manera de utilizar estas API es poner tu lógica (las cosas que te gustaría hacer con el país, la dirección ...) dentro de la devolución de llamada. – z33m

3

Derecha. La función que pase a getLocations() no se ejecutará hasta que los datos estén disponibles, por lo que devolver "país" antes de que se establezca no lo ayudará.

La forma en que necesita hacer esto es hacer que la función que pasa a geocoder.getLocations() realmente haga lo que quiera con los valores devueltos.

Algo como esto:

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 es posible que desee hacer algo diferente cada vez que se obtiene la ubicación, a continuación, pasar a la función como un parámetro adicional a 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 esto se ve un poco desordenado, entonces podría echar un vistazo a algo como la función Deferred en Dojo, que hace que el encadenamiento entre las funciones sea un poco más claro.

+0

Gracias, el problema que tengo sin embargo es que quiero usar el código de referencia inverso varias veces a lo largo de mi código. Tengo una lista de actualizaciones de estado y sus ubicaciones devueltas desde la API de Twitter, y por eso quiero llamar a reverseGeocode para cada una. Además, quiero llamar a reverseGeocode para la ubicación del usuario actual. No estoy seguro si eso tiene sentido ... el sitio está en http://www.chris-armstrong.com/whispers si quiere echar un vistazo y ver a qué me refiero –

+0

En caso de duda, utilice más funciones: -) Ver las ediciones anteriores ... –

1

Solo para FYI, Geocoder es asíncrono, por lo que la respuesta aceptada, aunque lógica, realmente no funciona en esta instancia. Preferiría tener un objeto externo que actúe como su actualizador.

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); 
       } 
     } 
    }); 
}; 
Cuestiones relacionadas