.then()
が約束を返すという3つの主な側面があります。その新しい約束が解決するまで
a().then(b).then(c).then(d)
.then()
が新たな約束を返すので、以下の.then()
ハンドラが実行されません。
最初は、あなたがこのようなチェーンオペレーションができるということです。 bとcが同期していれば、新しい約束はそれらが戻るときに解決され、最初にb
が完了した後、そしてc
が完了したときにチェーンが続行されます。
第2のは、新しい約束事が.then()
ハンドラが返すものの影響を受けることができるということです。これにより、b、c、dは非同期操作になり、それ自身は約束を返し、チェーンは適切に順序付けされます。だから、bとcの両方が約束を返すと想像してください。
まず、a()
に約束を返します。解決されると、その.then()
ハンドラが呼び出されます。それはb
を実行します。 b()
も非同期操作であり、新しい約束を返す場合、a.then(b)
は、返された新しい約束が解決されるまで、他のすべての.then()
ハンドラがリンクされていることを返します。これにより、.then()
ハンドラは新しい非同期アイテムをチェーンに挿入できます。これは約束の連鎖の非常に重要な側面です。.then()
ハンドラは、独自の非同期操作をチェーンに挿入することができ、以前の結果や現在の状態に基づいて条件付きで行うこともできます。
a().then(b)
はちょうど彼らがa()
約束にリンクされていたであろうと、それはすでに解決したので、a()
リターンは、その後、後続のすべての.then()
ハンドラがそのb()
リターンの約束のために、「待つ」ことができないだろうと同じ約束を返された場合。その新しい約束は、.then()
ハンドラが返すものの影響を受けるので、.then()
ハンドラ内の関数が後続のチェーンに影響を与えることを可能にするこの新しい約束の返却です。
第三側面は.then()
ハンドラの戻り値は、新たな約束の解決された値に影響を与えることができるということであり、それはチェーンの次の.then()
ハンドラに渡されるものです。 a()
が返す同じ約束を返したばかりの場合、a()
ハンドラはa()
から同じ解決された値を参照するだけです。a()
が解決された時点ですでに解決済みの値が設定されています。.then()
ハンドラこれらの後続の.then()
ハンドラは、.then()
ハンドラ内のコードから新しい解決された値を継承することができません。
具体的なシナリオを見てみましょう。私は遅延メソッドを、将来解決する約束を返す関数の簡単な例として使用します。
その後
function delay(t, val) {
return new Promise(resolve => {
setTimeout(() => resolve(val), t);
});
}
、いくつかの異なる非同期関数を定義する:
今
function a(val) {
return delay(100, val + 1);
}
function b(val) {
return delay(50, val + 10);
}
function c(val) {
return val * 100;
}
、チェーンにそれらをすべて入れ:
a(100).then(b).then(c).then(val => {
console.log("all done: ", val);
});
はここで段階的に何が起こるかです:
a(100)
はcalle d。これはdelay
(タイマーを設定します)を呼び出し、ここで説明するために私がa1_promise
と呼ぶ約束を返します。
我々はa(100).then(b)
をやっているので、その後、我々はa1_promise
とコールa1_promise.then(b)
あるa(100)
からの戻り値を取ります。これはa1_promise
が解決されたときにいつか呼び出される関数を.then()
ハンドラ関数として保存します(現時点ではそうではありません)。そしてそれは私がa2_promise
と呼ぶ新しい約束を返します。
我々はa(100).then(b).then(c)
をやっているので、その後、我々はa2_promise
とコールa2_promise.then(c)
あるa(100).then(b)
からの戻り値を取ります。 a2_promise
が解決された時点で、.then()
ハンドラ関数としてc
ファンクションがいつか呼び出されるようになりました。それから、私はa3_promise
と呼ぶ新しい約束を返します。
我々はa(100).then(b).then(c).then(...)
をやっているので、その後、我々はa3_promise
とコールa3_promise.then(c)
あるa(100).then(b),then(c)
からの戻り値を取ります。これは、a3_promise
が解決されたとき(将来はいつでも)、いつか呼び出される.then()
ハンドラ関数として最後の無名関数を格納します。その後、私はa4_promise
(誰も使用しない)と呼ぶ新しい約束を返します。
これで同期実行が完了しました。 a().then(b).then(c).then(...)
はすべて同期して実行されていたことに注意してください。すべての3つの.then()
メソッドは既にすべての異なる約束で呼び出されています。しかし、ここで作成された約束はまだ解決されていないので、.then()
ハンドラのどれも実際にはまだ呼び出されていません。約束が解決されたときに、彼らはすべて、将来呼び出されるようになったばかりです。
a()
の内部で作成されたタイマーが起動し、a1_promise
が解決されました。その後、a1_promise
をトリガして、.then()
ハンドラを呼び出し、a1_promise
という解決済みの値(この場合は100 + 1
または101
)を渡します。 a1_promise
にはただ1つの.then()
ハンドラがあり、それはb()
関数ですので、今度はb(101)
を呼び出します。それを実行すると、b()
が作成して返した新しい約束が返されます。我々はその新しい約束をb_promise
と呼ぶでしょう。 a1_promise()
内部には、それが保存されていること.then()
ハンドラを実行し、.then()
ハンドラが新しい約束を実行し、返すことをするとき、それはa2_promise that it created until that
b_promise is resolved. In this way, you can see that further execution of the chain is now controlled by the
b_promise , thus the code executing in
Bの解決にオフに保持していることを知っているようa1_promise.then()
が以前に呼び出されたとき、それはa2_promise()
を作成したことを知っています()and the promise is returned are inserted into the
a()。then()。then()。then()chain holding off future
.then()handlers until the
b_promise`が解決されました。
は現在、いくつかのより多くの時間が経過すると、タイマーはb()
火災の内部で作成され、111
ある101 + 10
の新しく変更された値を持つb1_promise
を解決します。これにより、a2_promise
はその値で解決できるようになります。
a2_promise
は、それが.then()
ハンドラだ呼び出すことができますし、もう一度だけc_promise
6リターンステップのように、まだ解決されていないc(111)
を実行することができます。
いくつかの時間が経過するとc_promise
は今、その値に解決できることを111 * 100 which is
11,100 . That tells the
a3_promise`の値を解決します。それを呼び出すことができます
a3_promiseはチェーンの終わりに私たちの矢印機能がある.then()
ハンドラだと我々は最終的な値として示すconsole.log()
11000
を取得します。
私はカイルシンプソンの本「あなたが知らないJS:非同期&パフォーマンス」をお勧めします。それは、連鎖のような明白なものを越えて、約束の利益について詳細に説明します。 –