简体   繁体   中英

Why is this promise chain not returning sequentially?

I'm trying to create a promise chain that returns the results in the order that they are called, as this is important for my application. However, despite a number of attempts I'm struggling as the output resultArray is coming back with some of the data points swapped, which screws up the downstream processing. This is what I have currently (found on

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});
});

I have also tried the following pattern, but this just returns [] as the promise.all doesn't appear to wait for the promises to finish as intended:

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});
});

UPDATE

Although the question as written was answered, I now realise that the accepted answer does not wait for each promise to return before the next is launched. It does map them so that the output is in the correct order, but I need each call to have a knowledge of the last - how do I achieve this succcinctly?

Don't use forEach & [].push if you want to get the data in order. Add the promises to the array and pass that array of promises to Promise.all that will keep the order for you.

Also your let p = Promise.resolve() line is not making any sense, it's just adding noise to your code.

Use .map to get an array of getElevation promises, and pass it to Promise.all , when it resolves the results will have the same order as data array.

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

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

You can make use of async/await pattern if you want each promise to resolve completely before the next promise. This way every call has access to all the results of the previous calls.

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 });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM