首页 > 解决方案 > 如何在 JavaScript 中将 Promise 链接在一起

问题描述

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

这是我的演示代码:

    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 同时触发?

标签: javascriptpromisees6-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'); });

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

随后如何使用它们是附带的,但是,为了让您的示例正常工作,编写调用时返回Promise 的函数可能会更好......所以:

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']);


推荐阅读