web-dev-qa-db-ja.com

javascriptの約束をブロックして解決された結果を返す方法は?

私は明らかに、jsの約束が解決される方法について、または「リターン」のセマンティクスについて何かを誤解しています。

私は同期することを期待する関数によって呼び出されています-値を返します。その値を計算するには、いくつかの非同期コードが必要です(具体的には、 dstore Collection のForEachメソッド

私が達成しようとしているのはおおよそこれですが、関数mySynchronousFunctionに戻り値がないため、これは機能しません。

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

私はJSがシングルスレッド実装を許可しなければならないことを理解していますので、ブロックするのはクールではありませんが、非同期コードを同期コードに接着するためのパターンがなければなりません。

26
Chris Owens

JavaScriptの非同期操作から同期結果を作成することはできません。あなたはそれをすることはできません。操作の一部が非同期である場合、結果全体が非同期である必要があり、コールバック、Promise、または操作が完了して結果の準備ができたときに通信する他の何らかのメカニズムを使用する必要があります。

非同期操作がすでにpromiseを返している場合(これは次のようになります)、ラッパー関数からそれを返すだけです。

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

また、副作用を介して動作する関数が最適なデザインパターンになることはめったにないことにも注意してください。入力を渡し、解決されたプロミスを介して出力を返すようにし、副作用を完全に回避することもできます。

19
jfriend00

いいえ、非同期コードを同期させる方法はありません。非同期呼び出しを行ったら、結果を非同期的に処理する必要があります。

JavaScriptはシングルスレッドであるため、結果を待つブロッキングループを作成すると、結果を処理するコードが実行される機会がなくなります。

非同期関数から何かを返したい場合は、呼び出し元のコードが結果を非同期的に処理するために使用できるプロミスを返す必要があります。

9
Guffa