web-dev-qa-db-fra.com

Comment bloquer pour une promesse javascript et retourner le résultat résolu?

Je me méprends évidemment quelque chose sur la façon dont les promesses js sont résolues ou sur la sémantique du "retour".

Je suis appelé par une fonction qui m'attend à être synchrone - pour renvoyer une valeur. Le calcul de cette valeur nécessite du code asynchrone (en particulier, la méthode ForEach sur un Collection dstore

Ce que j'essaie d'accomplir est approximativement ceci, mais cela ne fonctionne pas dans la mesure où la fonction mySynchronousFunction n'a pas de valeur de retour.

function mySynchronousFunction() {
   var accumulator = {};
   var myPromise = doAsynchronousThingThatSideEffectsAccumulator();
   // Now my caller is expecting the value of accumulator.
   myPromise.then(function() {return accumulator;})
}

Je comprends que JS doit permettre des implémentations à un seul thread, afin que ce ne soit pas cool de bloquer, mais il doit y avoir un modèle de collage de code asynchrone à synchrone, que je viens de manquer.

26
Chris Owens

Vous ne pouvez pas faire un résultat synchrone d'une opération asynchrone en Javascript. Vous ne pouvez tout simplement pas le faire. Si une partie de votre opération est asynchrone, le résultat entier doit être asynchrone et vous devez soit utiliser un rappel, une promesse ou un autre mécanisme de ce type pour communiquer lorsque l'opération est terminée et que le résultat est prêt.

Si votre opération asynchrone renvoie déjà une promesse (à laquelle elle ressemble), vous devez simplement la renvoyer à partir de la fonction wrapper:

function myWrapperFunction() {
   var accumulator = {};
   var myPromise = doAsynchronousThingThatSideEffectsAccumulator(accumulator);
   // Now my caller is expecting the value of accumulator.
   return myPromise.then(function(result) {
       // operate on the accumulator object using the async result
       return accumulator;
   })
}

myWrapperFunction.then(function(accumulator) {
   // write your code here that uses the accumulator result
});

Vous pouvez également noter qu'une fonction qui fonctionne via des effets secondaires est rarement le meilleur modèle de conception. Vous pouvez aussi bien passer l'entrée et lui faire retourner la sortie via la promesse résolue et éviter complètement les effets secondaires.

19
jfriend00

Non, il n'y a aucun moyen de synchroniser le code asynchrone. Une fois que vous avez effectué un appel asynchrone, vous devez gérer le résultat de manière asynchrone jusqu'au bout.

JavaScript est un thread unique, donc si vous faites une boucle de blocage qui attend le résultat, le code qui prend en charge le résultat n'aura aucune chance de s'exécuter.

Si vous souhaitez renvoyer quelque chose à partir d'une fonction asynchrone, vous devez renvoyer une promesse que le code appelant peut utiliser pour gérer le résultat de manière asynchrone.

9
Guffa