web-dev-qa-db-ja.com

Promiseチェーンを介した変数の受け渡し

これを行うためのより良い方法はありますか?

let foo;
return functionA().then(result => {
  foo = result;
  return functionB();
}).then(bar => {
  return functionC(foo, bar);
});

functionAの結果はfunctionCへの入力が必要であることに注意してください。 promiseスコープ外の変数を使用することは問題なく機能しますが、ちょっと厄介な感じがします。これを行うためのクリーンな慣用的な方法はありますか?

呼び出している関数のAPIを変更する機会がないことに注意してください。

8
Tim Scott

Promise.all() を使用してみると、promiseの配列を渡すことができ、渡されたすべてのpromiseが解決されると、then()コールバック内で応答の配列が提供されます。 。これらの配列値にアクセスして、functionCに渡すことができます。

Promise.all([functionA, functionB]).then(values => functionC(values[0], values[1]));

functionAからの応答をfunctionBに渡す必要があるようには見えないため、(ネストせずに)少しクリーンになる可能性があります。

それ以外の場合、ネストは次のようになります。

return functionA().then(foo => {
    return functionB().then(bar => {
        return functionC(foo, bar);
    });
});

うまくいけば、それが役立つでしょう。

1つのオプションは、 Alexander Staroselsky が書いているように、Promise.all(functionA(), functionB())を使用することです。これにより、2つの機能が同時に実行されます。それがあなたが起こりたいことであるならば、あなたはその答えを使うことができます。ただし、それらを次々に発生させてから、結果を別のハンドラーに渡すこともできるようにする場合は、次のようにします。

_function functionA() {
  return new Promise(resolve => resolve(1));
}

function functionB() {
  return new Promise(resolve => resolve(2));
}

function functionC(first, second) {
  return first + second;
}

functionA()
  .then(result => Promise.all([result, functionB()]))
  .then(function([first, second]) {
    return functionC(first, second);
  })
  .then(result => {
    console.log(result);
  });_

関数は明らかに単純化されていますが、Promisesのすばらしい点は、それが問題ではないことです。関数がどれほど複雑で、どれだけ時間がかかるかは関係ありません。イェーイ約束!

賢いのは、渡した値がPromiseでなくても、_Promise.all_は気にしないということです。それらが他の値である場合、それらは即座に解決される約束として扱われます。 (Promise.resolve(42).then(...)を実行できるのと同じ方法で。)したがって、Promise.all([result, functionB()])を実行できます。これは、「resultfunctionB()の両方の最終値があり、両方の値を渡すと解決されるPromiseを教えてください」と言います。これは、resultの場合はすぐに、functionBの場合は不特定の時間に発生します。

返された値は、配列として次のthen関数に渡されます。

_.then(function([first, second]) {
  return functionC(first, second);
})
_

次に、これは値を配列として受け取り(パラメーターリストのdestructuringの使用を参照)、それらの値をfunctionCに送信します。次に、最後のthen関数を実行して、結果を表示します。

5
lonesomeday