-1

How can functions be used to asynchronously fetch information to later re-use in another function?

The following code shows what is happening. I have a function getInfo which in turn uses getDependencies to fetch some information.

In the function itself the data is returned successfully. But when I want to use that in the other function, it shows an array of Promises.

const request = async function(url) {
  return fetch(url)
    .then(res => res.json())
    .catch(err => { console.warn(err) });
};

const getDependencies = async function(items) {
  return items.map(async (item) => {
    await request(item.url).then((res) => {
      console.log('res: ', res);
      // it successfully logs the response here...
      // res: { name: 'myObject' }
      // this happens 5 times

      // I would like to adjust the object for
      // each item it wil return
      return { name: item.name, res };
    });
  });
}

const getInfo = async function(details) {
  return details.map(async (detail) => {
    const result = await getDependencies(detail.items);
    // but here it is showing that there are 5 promises instead of the results
    console.log(result)
    // result: (5) [Promise, Promise, Promise, Promise, Promise]
  });
}
Remi
  • 4,663
  • 11
  • 49
  • 84
  • 3
    i believe you should take a look at Promise.all() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all – Kevin.a Sep 06 '20 at 19:22
  • How would that work together with adjusting the item in each iteration of the map function? I'd like it to return an object with a specific name per item, and than the result of the request function. – Remi Sep 06 '20 at 19:27

2 Answers2

0

You cannot return the fulfillment values from the future. You can however return a promise for an array instead of an array of promises, using Promise.all.

function request(url) {
  return fetch(url).then(res => res.json())
}

function getDependencies(items) {
  return Promise.all(items.map(async (item) => {
//       ^^^^^^^^^^^
    const res = await request(item.url);
    console.log('res: ', res);
    return { name: item.name, res };
  }));
}

function getInfo(details) {
  return Promise.all(details.map(async (detail) => {
//       ^^^^^^^^^^^
    const result = await getDependencies(detail.items);
    console.log(result)
  }));
}
    
getInfo([…]).catch(err => {
  console.warn(err);
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Ah dang. I was familiar with the Promise.all. But overlooked the fact that I should use that method on both instances. Thanks – Remi Sep 06 '20 at 19:38
0

This return details.map(async (detail) => { does not resolve every Promise before setting the result in the array, the async keyword makes the function return a Promise.

Try this instead:

const getInfo = function(details) {
  return details.map(detail => getDependencies(detail.items));
}

const result = await Promise.all(getInfo(details));
console.log(result);
Guerric P
  • 30,447
  • 6
  • 48
  • 86