2

I have the following data structure:

[
  {
    "id": 1,
    "houses": [
      {
        "id": 1,
        "name": "house 1"
      },
      {
        "id": 2,
        "name": "house 2"
      }
    ]
  },
  {
    "id": 2,
    "houses": [
      {
        "id": 3,
        "name": "house 3"
      }
    ]
  }
]

And I want to be able to, for each house in each user do something async, so I have a function with this signature and which returns a promise:

sendWelcomeEmail(user, house)

Now, I know how to use Bluebird's Promise.map when I have an array of promises, but in this case, I have an array of objects with arrays. What is the proper way to call Promise.map so I end up calling sendWelcomeEmail for each user and house?

2 Answers 2

1

Promise.all

The Promise.all(iterable) method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects.

const data = [{
    "id": 1,
    "houses": [{
        "id": 1,
        "name": "house 1"
      },
      {
        "id": 2,
        "name": "house 2"
      }
    ]
  },
  {
    "id": 2,
    "houses": [{
      "id": 3,
      "name": "house 3"
    }]
  }
];

const fakeSendWelcomeEmail = (id, house) => Promise.resolve(`${id} / ${house.name}`);

// Transforming the data into a flat array that contains the return value of fakeSendWelcomeEmail .
// So welcomeResults is an array of Promise.
const welcomeResults = data.reduce((res, user) => {
  return res.concat(user.houses.map((house) => {
    return fakeSendWelcomeEmail(user.id, house)
  }));
}, [])

Promise.all(welcomeResults)
  .then((results) => {
    console.log(results);
  })

I've written a Promise polyfill myself, if you're curious about how stuff works under the hood, or just learn a bit more about Promise.

Sign up to request clarification or add additional context in comments.

7 Comments

Bruno do you mind explaining what does this do? Promise.all is supposed to receive an iterable of promises, and in this case you are just passing an array to it.
@HommerSmith it accepts an Array of anything - if the element is a Promise, it waits for it to resolve, if it's a value, it resolves with that value
Why do you prefer using Promise.all vs Promise.map? The good thing with map is that you can have concurrency limits...
I am improving my answer, let me know there's something is still not clear
@HommerSmith Promise.all is part of the Promise's standard. Promise.map implementation depends on the particular library you're using.
|
0

You will need to combine reduce with map.

const promises = mainArray.reduce((acc, cur) => {
  return acc.concat(cur.houses.map(house => sendWelcomeEmail(house)));
}, []);

promises will be an array with 3 promises as per your example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.