web-dev-qa-db-fra.com

Comment retourner une valeur depuis une fonction de rappel asynchrone?

Cette question est posée à plusieurs reprises dans SO. Mais je ne peux toujours pas avoir de trucs.

Je veux obtenir une valeur de rappel. Regardez le script ci-dessous pour plus de précisions.

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 j'essaie de renvoyer cette valeur, elle devient simplement "non définie". J'ai suivi certaines idées de SO, mais j'échoue toujours.

Ce sont:

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

Cela est impossible car vous ne pouvez pas revenir d'un appel asynchrone dans une méthode synchrone.

Dans ce cas, vous devez passer un rappel à foo qui recevra la valeur de retour.

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

Le fait est que, si un appel de fonction interne est asynchrone, toutes les fonctions qui "encapsulent" cet appel doivent également être asynchrones pour pouvoir "renvoyer" une réponse.

Si vous avez beaucoup de rappels, vous pouvez envisager de franchir le pas et utiliser un bibliothèque de promesses comme Q .

431
Sean Kinsey

Cela n'a aucun sens de renvoyer les valeurs d'un rappel. Au lieu de cela, faites le "foo ()" travail que vous voulez faire à l'intérieur votre rappel.

Les rappels asynchrones sont appelés par le navigateur ou par un environnement tel que la bibliothèque de géocodage de Google lorsque des événements se produisent. Il n'y a pas de place pour les valeurs retournées. Une fonction de rappel peut renvoyer une valeur, autrement dit, mais le code qui appelle la fonction ne prête pas attention à la valeur de retour.

21
Pointy

Si vous utilisez jQuery, vous pouvez essayer ceci: http://api.jquery.com/category/deferred-object/

Il vous permet de différer l'exécution de votre fonction de rappel jusqu'à ce que la demande ajax (ou toute opération asynchrone) soit terminée. Cela peut également être utilisé pour appeler un rappel une fois que plusieurs demandes ajax sont toutes terminées.

15
Alex Heyd