2011-07-27 13 views
326

Esta pregunta se hace muchas veces en SO. Pero aun así no puedo obtener cosas.¿Cómo devolver el valor de una función de devolución de llamada asincrónica?

Quiero obtener algún valor de la devolución de llamada. Mira el guión a continuación para aclararlo.

function foo(address){ 

     // google map stuff 
     geocoder.geocode({ 'address': address}, function(results, status) { 
      results[0].geometry.location; // I want to return this value 
     }) 

    } 
    foo(); //result should be results[0].geometry.location; value 

Si trato de devolver ese valor acaba siendo "indefinido". Seguí algunas ideas de SO, pero aún falla.

Esos son:

function foo(address){ 
    var returnvalue;  
    geocoder.geocode({ 'address': address}, function(results, status) { 
     returnvalue = results[0].geometry.location; 
    }) 
    return returnvalue; 
} 
foo(); //still undefined 
+11

Cualquiera que haya llegado aquí [** lea primero esta pregunta **] (http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call). Explica cómo abordar este problema de manera efectiva. –

+0

** [¿Por qué mi variable permanece inalterada después de que la modifique dentro de una función? - Referencia de código asíncrono] (http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) ** también proporciona una explicación más general y detallada del problema en cuestión. –

+0

Usa Q, o cualquiera de sus variantes, como la biblioteca $ q que viene con angularJs. Y nunca mires atrás. Las funciones asíncronas devuelven inmediatamente indefinido. Así que nunca pierdas tu tiempo intentando hacer cosas indefinidas. Además, nunca use la palabra clave 'return' en sus funciones asíncronas, como lo hace normalmente. Use promesas diferidas en su lugar. deferred.resolve (STUFF que desea hacer), luego puede simplemente devolverlo, 'return deferred.promise; '. :) – ISONecroMAn

Respuesta

336

Esto es imposible ya que no puede regresar de una llamada asincrónica dentro de un método síncrono.

En este caso se necesita pasar una devolución de llamada a foo que recibirá el valor de retorno

function foo(address, fn){ 
    geocoder.geocode({ 'address': address}, function(results, status) { 
    fn(results[0].geometry.location); 
    }); 
} 

foo("address", function(location){ 
    alert(location); // this is where you get the return value 
}); 

La cosa es, si una llamada a la función interna es asíncrona, entonces todas las funciones 'envoltorio' Esta llamada debe también ser asíncrono para 'devolver' una respuesta.

Si tiene muchas devoluciones de llamada, puede considerar lanzarse y usar un promise library like Q.

+3

:) No es fuerte, es solo como es. Tan pronto como utiliza un método asíncrono para pasar datos, toda la cadena de funciones se vuelve asincrónica. –

+0

Si la cadena de funciones asíncronas manipula un objeto, digamos un objeto 'gráfico'. ¿Hay alguna forma de obtener una referencia a ese objeto para llamar algo como update()? – user2483724

+2

Voto por hacer que esto tenga sentido. –

18

No tiene sentido para devolver valores de una devolución de llamada. En su lugar, realice el trabajo "foo()" que desea hacer dentro de su devolución de llamada.

Las devoluciones de llamada asincrónicas son invocadas por el navegador o por algún marco como la biblioteca de geocodificación de Google cuando ocurren eventos. No hay lugar para que los valores devueltos vayan. Una función de devolución de llamada puede devolver un valor, en otras palabras, pero el código que llama a la función no prestará atención al valor devuelto.

14

Si se esté utilizando jQuery, es posible que desee dar a este un tiro: http://api.jquery.com/category/deferred-object/

Se le permite diferir la ejecución de la función de devolución de llamada hasta que la solicitud Ajax (o cualquier operación asíncrona) se completa . Esto también se puede usar para llamar a una devolución de llamada una vez que se hayan completado todas las solicitudes ajax.

Cuestiones relacionadas