如何在 JavaScript 中将 promise 链接在一起

How to chain promises together in JavaScript

我正在尝试链接一系列 Promise,以便第二个 promise 将在第一个 promise 解决后开始,依此类推。我不明白我怎么不能让它正常工作。

这是我的演示代码:

    const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'a'); });
    const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'b'); });
    const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'c'); });

    promise1.then(val => {
      console.log('promise 1', val);
      promise2.then(val2 => {
        console.log('promise 2', val2);
        promise3.then(val3 => {
          console.log('promise 3', val3);
        });
      });
    });

所以我对这段代码的期望是这样的:

--- 5 seconds passes ---
// console outputs: 'promise 1a'
--- 5 seconds passes ---
// console outputs: 'promise 2b'
--- 5 seconds passes ---
// console outputs: 'promise 3c'

但相反会发生什么:

--- 5 seconds passes ---
// console outputs: 'promise 1a'
// console outputs: 'promise 2b'
// console outputs: 'promise 3c'

为什么会这样?为什么三个promise同时触发?

为了解释为什么它们同时完成,我们可以忽略除 promise 声明之外的所有内容:

const promise1 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'a'); });
const promise2 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'b'); });
const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 5000, 'c'); });

这些承诺是 HOT 创建的(即立即调用传递给构造函数的处理程序),并且都是同时创建的。因此,无论后续如何使用,setTimeout 都会在 5 秒内触发。

随后如何使用它们是附带的,但是,为了让您的示例正常工作,最好编写 return[=38= 的函数] 调用时承诺... 所以:

const getPromise1 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'a');
});
const getPromise2 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'b');
});
const getPromise3 = () => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, 'c');
});

getPromise1().then((val1) => {
  console.log(val1);
  return getPromise2(); //by returning Promise, you can avoid deep nesting
}).then((val2) => {
  console.log(val2);
  return getPromise3();
}).then((val3) => {
  console.log(val3);
});

在回答评论时,最好有一个参数数组用于提供给 Promise-returning 函数,然后使用 async/await 编写调用 Promise-returning函数顺序

const getPromise = (v) => new Promise((resolve, reject) => {
  setTimeout(resolve, 5000, v);
});

async function run(params) {
  for (const p of params) {
    const returnVal = await getPromise(p);
    console.log(returnVal);
  }
}

run(['a', 'b', 'c']);

Promise 在您声明后立即启动,.then() 函数只是一个“onResolve”事件,即在解决 promise 时调用。 要执行您想要的操作,您需要使用 5、10 和 15 秒超时。

如果您想要仅在调用时才启动的内容,请查找 RxJS。这是一个很棒的库,具有一些有用的功能来解析和链接响应。 RxJS 创建 observables 仅当某些东西 subscribe 时才会启动。