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

时间:2018-02-13 20:28:38

标签: javascript promise resolve

我有一个承诺,当它结算时,它将返回“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();
            });
        }

3 个答案:

答案 0 :(得分:2)

使用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()

EDIT2:

您是否在每个功能中声明了xhttp?这需要在两者内部。

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

答案 1 :(得分:1)

安德鲁对Promise.all的使用完全正确,你应该使用它。

  

始终打印最后一个承诺的值并跳过第一个承诺。为什么会这样?

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

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

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

答案 2 :(得分:-1)