Hommer Smith
Hommer Smith

Reputation: 27852

Promise map with array of objects with arrays

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?

Upvotes: 2

Views: 76

Answers (2)

Bruno
Bruno

Reputation: 6000

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.

Upvotes: 1

yBrodsky
yBrodsky

Reputation: 5041

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.

Upvotes: 0

Related Questions