Search code examples
javascriptes6-promisedestructuring

using a config object with Promise.all()


I am looking at using Promise.all() to fetch data from multiple endpoints. With Promise.all() an array is returned and you can destructor the items from that array e.g.

const [fetch1, fetch2] = Promise.all(urls.map(url => fetch(url)))

I am looking for way to dynamically name those destructured items (name1 and name2) using a config object.

const urls = [
  {
    name: 'google',
    url: 'https://www.google.com'
  },
  {
    name: 'bbc',
    url: 'https://www.bbc.co.uk'
  }
]

const [google, bbc] = Promise.all(urls.map(url => fetch(url.url)))

In the above example items destructured from the promise.all should use the name from the urls array i.e. urls.name

Essentially I am looking for a way to name my exports in the config object that is passed to promise.all()

the main reason for this is that data returned from these promises you be keyed under the name specified in the urls config object. so we could also do

const data = Promise.all(urls.map(url => fetch(url.url)))
console.log(data.google || data.bbc)

Solution

  • This should do:

    const fetchUrl = (url) => fetch(url.url).then((response) => ({ [url.name]: response }));
    
    const mergeResults = (results) => results.reduce(
      (mergedResults, result) => ({ ...mergedResults, ...result }),
      {}
    );
    
    const data = Promise
      .all(urls.map(fetchUrl))
      .then(mergeResults)
      .then((data) => {
        console.log(data.google || data.bbc);
      });
    

    Bergi's update:

    const data = Promise
      .all(urls.map(fetchUrl)) // same as above
      .then((results) => Object.assign({}, ...results)) // elegance++
      .then((data) => {
        console.log(data.google || data.bbc);
      });