通过 Promise 链传递变量

Passing Variables Through a Promise Chain

有更好的方法吗?

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

注意 functionA 的结果需要输入到 functionC。在 promise 范围之外使用变量工作正常,但感觉有点恶心。有没有一种干净的惯用方法可以做到这一点?

请注意,我没有机会更改我正在调用的任何函数的 API。

您可以尝试使用 Promise.all(),您可以传递一组承诺,并且当传入的所有承诺都已解决时,它会在 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);
    });
});

正如所写,一个选择是使用Promise.all(functionA(), functionB())。这会同时运行这两个函数。如果那是你想要发生的事情,你可以使用那个答案。但是,如果您希望它们一个接一个地发生,然后还能够将结果传递给另一个处理程序,您可以这样做:

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.all 不会介意您传递的值不是 Promises。如果它们是任何其他值,它们将被视为立即解决的 Promise。 (就像你可以做 Promise.resolve(42).then(...) 一样。)所以我们可以做 Promise.all([result, functionB()])。这表示 "give me a Promise that is resolved when you have a final value for both result and functionB() and pass both values on"。在 result 的情况下立即发生,在 functionB.

的情况下在某个未指定的时间发生

然后将返回值作为数组传递给下一个 then 函数。

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

然后将值作为数组接收(请参阅参数列表中解构的使用)并将这些值发送到 functionC。然后我们执行最后一个 then 函数来显示结果。