明示的なパススルー
コールバックのネストと同様に、この手法はクロージャに依存しています。ただし、チェーンはフラットのままです。最新の結果のみを渡すのではなく、一部の状態オブジェクトがすべてのステップで渡されます。これらの状態オブジェクトは、前のアクションの結果を蓄積し、後で再び必要になるすべての値と現在のタスクの結果を伝えます。
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(b => [resultA, b]); // function(b) { return [resultA, b] }
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
ここで、その小さな矢印b => [resultA, b]
はを閉じる関数でresultA
あり、両方の結果の配列を次のステップに渡します。これは、パラメータ分解構文を使用して、単一の変数に再度分割します。
ES6で解体が可能になる前.spread()
は、多くのpromiseライブラリ(Q、Bluebird、 when、…)。これは、複数のパラメーター(配列要素ごとに1つ)を持つ関数を使用して、.spread(function(resultA, resultB) { …
ます。
もちろん、ここで必要なクロージャーは、いくつかのヘルパー関数によってさらに簡略化できます。
function addTo(x) {
// imagine complex `arguments` fiddling or anything that helps usability
// but you get the idea with this simple one:
return res => [x, res];
}
…
return promiseB(…).then(addTo(resultA));
または、Promise.all
配列のpromiseを生成するために採用できます。
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return Promise.all([resultA, promiseB(…)]); // resultA will implicitly be wrapped
// as if passed to Promise.resolve()
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
また、配列だけでなく、任意に複雑なオブジェクトを使用する場合もあります。たとえば、別のヘルパー関数で、_.extend
またはそのObject.assign
中で:
function augment(obj, name) {
return function (res) { var r = Object.assign({}, obj); r[name] = res; return r; };
}
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(augment({resultA}, "resultB"));
}).then(function(obj) {
// more processing
return // something using both obj.resultA and obj.resultB
});
}
このパターンはフラットチェーンを保証し、明示的な状態オブジェクトは明確性を向上させることができますが、長いチェーンでは面倒になります。特に、散発的にしか状態を必要としない場合は、すべてのステップを通過する必要があります。この固定されたインターフェースにより、チェーン内の単一のコールバックはかなり密に結合され、変更に柔軟性がなくなります。これにより、シングルステップの因数分解が困難になり、コールバックを他のモジュールから直接提供することはできません。これらは常に、状態を気にするボイラープレートコードでラップする必要があります。上記のような抽象的なヘルパー関数は少し苦痛を軽減できますが、常に存在します。
javascript
、タグが付けられていても、他の言語に関連しています。私はJavaとjdeferredで「チェーンを壊す」という答えを使用しています