在 javascript 的 .then() 子句中调用两个 promise

call two promises in the .then() clause in javascript

我有一个承诺,当它解决时,它会 return "ResponseA" 并且在 .then() 子句中它应该调用另外两个承诺,当它们实现时,它应该打印输出值(tgResponse.length 和 igResponse.length)。但问题是,它总是打印最后一个承诺的值并跳过第一个 console.log('igResponse', igResponse.length); 为什么会这样?以及如何确保它并行运行 igApiPromise 和 tgApiPromise 并打印它们的值。非常感谢你的帮助。

这是我的代码:

new Promise((resolve, reject) => {
            /// do some stuff
                    resolve(responseA)
                }
            });
        }).then(ResponseA => {
            console.log(ResponseA.Values);
            igApiPromise(ResponseA.Values.token).then(igResponse => {
                console.log('igResponse', igResponse.length);
            });
            tgApiPromise(ResponseA.Values).then(tgResponse => {
                console.log('tgResponse', tgResponse.length);
            });  
         });

        let igApiPromise = token => {
            return new Promise(function (resolve, reject) {
                console.log('lotfan');
                xhttp.open("GET", "/api/igconfig", true);
                xhttp.setRequestHeader("Authorization", `Bearer ${token}`);
                xhttp.onload = function () {
                    if (this.status >= 200 && this.status < 300 && this.readyState == 4) {
                        resolve(xhttp.response);
                    } else {
                        reject({
                            status: this.status,
                            statusText: xhttp.statusText
                        });
                    }
                };
                xhttp.onerror = function () {
                    reject({
                        status: this.status,
                        statusText: xhttp.statusText
                    });
                };
                xhttp.send();
            });
        }

        let tgApiPromise = token => {
            return new Promise(function (resolve, reject) {
                xhttp.open("GET", "/api/tgApidata", true);
                xhttp.setRequestHeader("Authorization", `Bearer ${token}`);
                xhttp.onload = function () {
                    if (this.status >= 200 && this.status < 300 && this.readyState == 4) {
                        resolve(xhttp.response);
                    } else {
                        reject({
                            status: this.status,
                            statusText: xhttp.statusText
                        });
                    }
                };
                xhttp.onerror = function () {
                    reject({
                        status: this.status,
                        statusText: xhttp.statusText
                    });
                };
                xhttp.send();
            });
        }

使用 Promise.all 应该是这样的:

new Promise((resolve, reject) => {
      resolve(responseA)
    }
  });
}).then(ResponseA => {
  const igPromise = igApiPromise(ResponseA.Values.token)
  const tgPromise = tgApiPromise(ResponseA.Values)
  return Promise.all([igPromise, tgPromise])
}).then(responses => {
  const igResponse = responses[0]
  const tgResponse = responses[1]
  console.log('igResponse', igResponse.length)
  console.log('tgResponse', tgResponse.length)
})

此外,如果您将函数 igApiPromisetgApiPromise 放在您使用它的地方下面,请不要进行变量赋值。使用 function 语法。

function igApiPromise(token) {
}

我很惊讶你的原始代码没有抛出错误。

编辑:那么您的 api 调用有问题。这个带有 Promise.all 的准系统示例工作得很好。正如预期的那样,它在 6 秒内完成。

function runProm() {
  return new Promise((resolve, reject) => {
      setTimeout(() => resolve('1000'), 2000)
  }).then(ResponseA => {
    const igPromise = igApiPromise(ResponseA)
    const tgPromise = tgApiPromise(ResponseA)
    return Promise.all([igPromise, tgPromise])
  }).then(responses => {
    const igResponse = responses[0]
    const tgResponse = responses[1]
    console.log('igResponse', igResponse)
    console.log('tgResponse', tgResponse)
  })
}

function igApiPromise(token) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve('eyegApiPromise' + token), 4000)
  })
};

function tgApiPromise(token){
  return new Promise((resolve, reject) => {
      setTimeout(() => resolve('teegApiPromise' + token), 40)
  })
}

runProm()

编辑2:

您是否在每个函数中声明了 xhttp?这需要在两个里面。

let igApiPromise = token => {
  var xhttp = new XMLHttpRequest()
}

您可以尝试使用 ES7 的异步等待功能。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function

Andrew 关于 Promise.all 的使用的回答完全正确,你应该使用它。

It is always printing the value of last promise and skipping the first one. Why this happens?

我猜你的实际问题是你有一个全局 xhttp 变量和一个 XMLHttpRequest 实例,你的两个函数都使用它。它们不能同时 运行 因为最后一次调用覆盖了前一次调用安装的处理程序。

在使用前为每个函数调用创建一个新的。

function …ApiPromise(token) {
    return new Promise(function (resolve, reject) {
         const xhttp = new XMLHttpRequest();
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         xhttp.open("GET", …);
         …
    });
}