web-dev-qa-db-ja.com

Promiseの本体はいつ実行されますか?

次のPromiseがあるとします:

_function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    const result = doSomeWork();

    setTimeout(() => {
      resolve(result);
   }), 100);
  });
}
_

doSomeWork()はどの時点で呼び出されますか? Promiseが作成された直後ですか、それとも作成されていますか?そうでない場合、Promiseの本体が実行されることを確認するために明示的に行う必要がある追加の何かがありますか?

38
Kevin

すぐに、はい、仕様により。

MDN から:

Executor関数はPromise実装によって直ちに実行され、resolveおよびreject関数を渡します(Promiseコンストラクターが作成されたオブジェクトを返す前にexecutorが呼び出されます)

これはECMAScript仕様にあります(もちろん読みにくい...): http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

この保証は、たとえば、いくつかのプロミスを準備しているときにallまたはraceに渡す場合、またはエグゼキューターに同期的な副作用がある場合に重要です。

34
Denys Séguret

はい、Promiseを作成すると、最初のパラメーターがすぐに実行されます。

一般に、現在の実装と同じように、promiseを実際に使用することはありません。

タイムアウトを使用して実装するか、ajaxコールバックの一部として解決関数を呼び出します

function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    setTimeout(function() {
      const result = doSomeWork();
      resolve(result);
    }, 0);
  });
}

setTimeoutメソッドは、イベントキューが解放された次の瞬間に関数を呼び出します

6
Icepickle

下から、非同期ではなく同期コードを本体に入れるだけで、本体がすぐに実行されることがわかります。

_function doSomethingAsynchronous() {
  return new Promise((resolve) => {
    console.log("a");
    resolve("promise result");
  });
}
doSomethingAsynchronous();console.log("b");
_

結果は、promise本体がすぐに実行されることを示しています(「b」が出力される前)。

_a
b
_

Promiseの結果は保持され、たとえば「then」呼び出しにリリースされます。

_doSomethingAsynchronous().then(function(pr){console.log("c:"+pr);});console.log("b");
_

結果:

_a
b
c:promise result
_

約束が満たされ、「then」が呼び出される前の不確定な遅延を除いて、ボディの非同期コードも同様に処理されます(ポイント「c」)。したがって、doSomethingAsynchronous()が返るとすぐに 'a'と 'b'が出力されますが、約束が満たされた( 'resolve'が呼び出された)場合にのみ 'c'が表示されます。

「then」への呼び出しが追加されると、表面上は奇妙に見えますが、すべてが同期している場合でも「c」の前に「b」が出力されます。確かに「a」が印刷され、次に「c」、最後に「b」が印刷されますか? 「a」、「b」、「c」がこの順序で出力される理由は、本体のコードが非同期か同期かに関係なく、「then」メソッドがPromiseによって常に非同期に呼び出されるためです。

私の考えでは、「resolve」が呼び出されると、PromiseのsetTimeout(function(){then(pr);},0);のようなものによって呼び出される 'then'メソッドを想像します。つまり「then」に渡された関数が実行される前に、現在の実行パスが完了する必要があります。

Promise仕様から、なぜこれを行うのかは明らかではありません。私の推測では、すべてのPromises呼び出しを開始する前に複数のthenをスタック/チェーンできるようにするために、「then」が呼び出されるとき(常に現在の実行スレッドが終了した後)に一貫した動作を保証します連続して。

2
Moika Turns

EcmaScript仕様から http://www.ecma-international.org/ecma-262/6.0/#sec-promise-executor

Executor関数はPromise実装によって直ちに実行され、resolveおよびreject関数を渡します(Promiseコンストラクターが作成されたオブジェクトを返す前にexecutorが呼び出されます)

次のコードを検討してください。

var executorFunction = (resolve, reject) => {
    console.log("This line will be printed as soon as we declare the promise");
    if(asynkTaskCompleted){
        resolve("Pass resolved Value here");
    }else{
        reject("Pass reject reason here");
    }

}
const myPromise = new Promise(executorFunction);

上記のコードを実行すると、約束を宣言するとすぐにexecutorFunctionが自動的に呼び出され、明示的に呼び出す必要はありません。

1
Himansh