为什么这个承诺链没有按顺序返回?

时间:2019-12-22 18:49:46

标签: javascript node.js express promise

我正在尝试创建一个按结果顺序返回结果的承诺链,因为这对我的应用程序很重要。但是,尽管进行了许多尝试,但由于输出resultArray的返回却交换了一些数据点,我仍在挣扎中,这使下游处理更加麻烦。这就是我目前所拥有的(在

上找到
Promise.all(data.map( (dataPoint) => {
  return new Promise( (resolve, reject) => {
    doSomething(dataPoint).then( (result) => {
      resultArray.push(result);
      resolve();
    });
  })
})).then( () => {
    res.status(201).json({"result": resultArray});
});

我也尝试过以下模式,但是这只会返回[]作为promise。所有人似乎都没有等待诺言按预期完成:

let p = Promise.resolve();
data.forEach(dataPoint => {
  p = p.then( () => {
    getElevation(dataPoint, options).then( (result) => {
      resultArray.push(result);
    });
  });
});

Promise.all([p]).then( () => {
  res.status(201).json({"result": resultArray});
});

更新

尽管回答了所写的问题,但我现在意识到,接受的答案并不等待每个承诺在下一个承诺发布之前就返回。它会映射它们,以使输出按正确的顺序排列,但是我需要每个调用都了解最后一个-如何成功实现此目的?

2 个答案:

答案 0 :(得分:3)

如果要按顺序获取数据,请不要使用forEach[].push。将诺言添加到数组中,并将该诺言数组传递到Promise.all,这将为您保留订单。

您的let p = Promise.resolve()行也没有任何意义,只是在代码中增加了噪音。

使用.map获取getElevation承诺的数组,并将其传递给Promise.all,当它解析结果时,其顺序将与data数组相同。 / p>

const promises = data.map(dataPoint => getElevation(dataPoint, options));

Promise.all(promises).then(result => {
  res.status(201).json({ result });
});

答案 1 :(得分:0)

如果希望每个承诺在下一个承诺之前完全解决,则可以使用async/await模式。这样,每个呼叫都可以访问先前呼叫的所有结果。

async function run(options) {
  const results = [];
  for(let dataPoint of data) {
    const result = await getElevation(dataPoint, options);
    results.push(result);
  }
  return results;
}

run(options).then(result => {
  res.status(201).json({ result });
});