2011-07-27 5 views
326

Этот вопрос задан много раз в SO. Но все равно я не могу получить вещи.Как вернуть значение из асинхронной функции обратного вызова?

Я хочу получить некоторую ценность от обратного вызова. Посмотрите на сценарий ниже для уточнения.

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 

Если я попытаюсь вернуть это значение, просто получив «undefined». Я следил за некоторыми идеями из SO, но все еще не работает.

Те:

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

Любой, кто получил здесь [**, пожалуйста, сначала прочтите этот вопрос ** **) (http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call). В нем объясняется, как эффективно решать эту проблему. –

+0

** [Почему моя переменная не изменяется после того, как я изменяю ее внутри функции? - ссылка на асинхронный код] (http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) ** также обеспечивает более общее, подробное объяснение проблемы. –

+0

Используйте Q или любые его варианты, например, библиотеку $ q, которая поставляется с angularJs. И Никогда не оглядывайся назад. Асинхронные функции немедленно возвращаются не определены. Поэтому никогда не тратьте свое время на то, чтобы делать что-то неопределенное. Также никогда не используйте ключевое слово «return» в своих асинхронных функциях, как обычно. Вместо этого используйте отложенные обещания. отложенным.resolve (STUFF, который вы хотите сделать), а затем вы можете просто вернуть это, «return offfer.promise; ». :) – ISONecroMAn

ответ

336

Это невозможно, поскольку вы не можете вернуться из асинхронного вызова внутри синхронного метода.

В этом случае вам нужно передать обратный вызов Foo, который будет получать возвращаемое значение

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

Дело в том, если вызов внутренняя функция является асинхронным, то все функции «оборачивания» этот вызов должен также должны быть асинхронными, чтобы «вернуть» ответ.

Если у вас много обратных вызовов, вы можете подумать о погружении и использовать promise library like Q.

+3

:) Это не сильно, так оно и есть. Как только вы используете метод async для передачи данных, вся цепочка функций становится асинхронной. –

+0

Если цепочка асинхронных функций управляет объектом, скажем, объект 'graph'. В любом случае, я могу получить ссылку на этот объект, чтобы называть что-то вроде update() на нем? – user2483724

+2

Upvote для того, чтобы сделать это понятным. –

18

Это не имеет никакого смысла возвращать значения из функции обратного вызова. Вместо этого выполните «foo()» работу, которую вы хотите сделать внутри ваш обратный вызов.

Асинхронные обратные вызовы вызываются браузером или некоторыми фреймворками, такими как библиотека геокодирования Google, когда происходят события. Там нет места для возвращаемых ценностей. Функция обратного вызова может вернуть значение, другими словами, но код, вызывающий функцию, не будет обращать внимание на возвращаемое значение.

14

Если вам случится быть с помощью JQuery, вы можете дать этому выстрел: http://api.jquery.com/category/deferred-object/

Это позволяет отложить выполнение функции обратного вызова до запроса AJAX (или какой-либо операции асинхронной) завершается , Это также можно использовать для вызова обратного вызова после завершения нескольких запросов ajax.

Смежные вопросы