admin管理员组

文章数量:1415491

I'm working with some old code and I'm trying to return results for two arrays of promises.

So basically body contains first and second which are arrays of ids. I know that the below code works for a small array of of 1 to 5 ids, but if I were to do a few hundred, would the resolve fire before I get the hundred of results from both promise arrays?

 const doSomething = (body) => {
    return new Promise((resolve, reject) => {
      const promisesOne = body.first.map((id) => 
        doSomethingOne(id)
      );

      const promisesTwo = body.second.map((id) => 
        doSomethingTwo(id)
      );

      let response = {
        first: {}
        second: {}
        headers: 'mock headers'
      };

      Promise.all(promisesOne).then((results) => {
        response.first = results;
      });

      Promise.all(promisesTwo).then((results) => {
        response.second = results;
      });

      resolve(response);
  });
};

Also I won't be able to refactor this to async/await as this codebase does not use it.

I'm working with some old code and I'm trying to return results for two arrays of promises.

So basically body contains first and second which are arrays of ids. I know that the below code works for a small array of of 1 to 5 ids, but if I were to do a few hundred, would the resolve fire before I get the hundred of results from both promise arrays?

 const doSomething = (body) => {
    return new Promise((resolve, reject) => {
      const promisesOne = body.first.map((id) => 
        doSomethingOne(id)
      );

      const promisesTwo = body.second.map((id) => 
        doSomethingTwo(id)
      );

      let response = {
        first: {}
        second: {}
        headers: 'mock headers'
      };

      Promise.all(promisesOne).then((results) => {
        response.first = results;
      });

      Promise.all(promisesTwo).then((results) => {
        response.second = results;
      });

      resolve(response);
  });
};

Also I won't be able to refactor this to async/await as this codebase does not use it.

Share Improve this question asked Sep 12, 2022 at 2:57 ffx292ffx292 7093 gold badges20 silver badges35 bronze badges 3
  • FYI your code always returns resolve() before you get results, no matter how large your arrays are – Phil Commented Sep 12, 2022 at 3:10
  • Avoid the Promise constructor antipattern! – Bergi Commented Sep 12, 2022 at 4:04
  • I would if I could... Unfortunately, it isn't my codebase. – ffx292 Commented Sep 13, 2022 at 1:28
Add a ment  | 

2 Answers 2

Reset to default 5

would the resolve fire before I get the ... results from both promise arrays?

Yes, absolutely because you aren't waiting for them to resolve.

Simply wrap the two Promise.all() promises in another Promise.all() to wait for everything then create the final object you want.

const doSomething = (body) => {
  return Promise.all([
    Promise.all(body.first.map(doSomethingOne)),
    Promise.all(body.second.map(doSomethingTwo)),
  ]).then(([first, second]) => ({
    first,
    second,
    headers: "mock headers",
  }));
};

You could make this generic by creating a map of body property names to their corresponding mapping function. For example

const mappers = {
  first: doSomethingOne,
  second: doSomethingTwo,
};

const doSomething = (body) => {
  return Promise.all(
    Object.entries(mappers).map(([key, mapper]) =>
      Promise.all(body[key].map(mapper)).then((data) => ({ [key]: data }))
    )
  )
  .then((results) => Object.assign({ headers: "mock headers" }, ...results));
};

Your code will not work at the moment - the resolve(response) will run before either of the Promise.alls are done.

First, refactor your .first and .second (etc) properties so that they're arrays, rather than unique string properties. Then, it'll be easy to .map them with two Promise.alls - one to wait for an individual array to fulfill, and an outer one to wait for all arrays to fulfill.

The same thing should be done for the doSomethingOne etc functions - to make the code easy to work with, use an array of functions instead of having many standalone identifiers.

Also, there's no need for the explicit Promise construction antipattern.

const doSomethings = [
  doSomethingOne, // define these functions here
  doSomethingTwo,
];

const doSomething = (body) => Promise.all(
  body.arrayOfArraysOfIds.map(
    (arr, i) => Promise.all(
      arr.map(id => doSomethings[i](id))
    )
  )
)
  .then((results) => ({
    headers: 'mock headers',
    results,
  });

本文标签: javascriptHow can I wait for multiple Promiseall()Stack Overflow