web-dev-qa-db-ja.com

返り値とthen()からのPromise.resolveの違いは何ですか

違いは何ですか:

new Promise(function(res, rej) {
    res("aaa");
  })
  .then(function(result) {
    return "bbb";
  })
  .then(function(result) {
    console.log(result);
  });

この:

new Promise(function(res, rej) {
    res("aaa");
  })
  .then(function(result) {
    return Promise.resolve("bbb");
  })
  .then(function(result) {
    console.log(result);
  });

私は、Angularと$ httpサービスを連鎖して.then()を使用して、動作が異なることを確認しています。多すぎるコードなので、最初に上の例を見てください。

267
spirytus

ルールは、thenハンドラー内の関数が値を返す場合、promiseはその値で解決/拒否し、関数がpromiseを返す場合、次のthen句はthen句になります関数が返したプロミス。したがって、この場合、最初の例はthensの通常のシーケンスに該当し、期待どおりに値を出力します。2番目の例では、Promise.resolve("bbb")を実行すると返されるプロミスオブジェクトチェーン時に呼び出されるthenです(すべての意図と目的のため)。実際に機能する方法については、以下で詳しく説明します。

Promises/A +仕様からの引用:

約束解決手順は、入力として約束と値をとる抽象操作であり、これを[[Resolve]](promise, x)と表します。 xがthenableの場合、promise xの状態を採用しようと試みます。xは少なくともpromiseのように動作するという仮定の下で。そうでなければ、値xでpromiseを満たします。

Thenableのこの処理により、Promises/A +準拠のthenメソッドを公開している限り、Promise実装は相互運用できます。また、Promises/A +実装は、合理的なthenメソッドを使用して、非準拠の実装を「同化」できます。

ここで注意すべき重要な点は、次の行です。

xがプロミスの場合、その状態を採用[3.4]

リンク: https://promisesaplus.com/#point-49

127
Hrishi

あなたの例は両方ともほとんど同じように振る舞うはずです。

then()ハンドラ内で返される値は、そのthen()から返されるpromiseの解決値になります。 .then内に返された値が約束である場合、then()によって返された約束はその約束の「状態を採用し」、返された約束と同じように解決/拒否します。

最初の例では、最初のthen()ハンドラーに"bbb"を返すので、"bbb"は次のthen()ハンドラーに渡されます。

2番目の例では、"bbb"という値ですぐに解決されるpromiseを返すので、"bbb"は次のthen()ハンドラーに渡されます。 (ここのPromise.resolve()は無関係です)。

結果は同じです。

あなたが私たちに実際に異なる振る舞いを示す例を示すことができるならば、なぜそれが起こっているのかあなたに言うことができます。

85
JLRishe

簡単に言うと、thenハンドラ関数の中では、

A)xが値(数値、文字列など)の場合:

  1. return xreturn Promise.resolve(x)と同等です
  2. throw xreturn Promise.reject(x)と同等です

B)xがすでに決済されている(もう保留されていない)Promiseの場合:

  1. Promiseがすでに解決されている場合、return xreturn Promise.resolve(x)と同等です。
  2. Promiseがすでに拒否されている場合、return xreturn Promise.reject(x)と同等です。

C)xが保留中の約束である場合:

  1. return xは保留中のPromiseを返し、それは後続のthenで評価されます。

このトピックに関する Promise.prototype.then()docs に関する詳細を読んでください。

63
Arian Acosta

あなたはすでに良い正式な答えを得ました。私は短いものを追加するべきだと考えました。

以下のことは Promises/A + promisesと同じです。

  • Promise.resolveを呼び出す(Angularの場合は$q.when
  • Promiseコンストラクタを呼び出し、そのリゾルバで解決します。あなたの場合はnew $qです。
  • thenコールバックから値を返します。
  • 値を持つ配列に対してPromise.allを呼び出してから、その値を抽出します。

したがって、次のものは、約束またはプレーンな値Xに対してすべて同じです。

Promise.resolve(x);
new Promise(function(resolve, reject){ resolve(x); });
Promise.resolve().then(function(){ return x; });
Promise.all([x]).then(function(arr){ return arr[0]; });

そして当然のことながら、promise仕様は Promise Resolution Procedure に基づいています。これにより、ライブラリ間の相互運用が容易になり($ qやネイティブの約束など)、生活全体が楽になります。約束された決議が発生するかもしれない時はいつでも決議は全体的な一貫性を作成しながら起こります。

46