Hugo Perez
Hugo Perez

Reputation: 135

Problems with async / await - How to wait for requests

I have an array of objects containing metadata for videos. I need to iterate through it and for each object I need to make an API call passing its filename to get a streamingLink and assign it to the object's streamingLink. My problem is by the time I am returning this array, the array is undefined. How do I tell the code to wait until streamingLink has been assigned?

Here's kind of what my code looks like:

// get array from database
const items = await client.db('database').collection('collection').find({}).toArray();

// for each object get and replace streamingLink
let items_withLinks = items.map((item) => {
  getStreamingLink(item.filename) // API call to get link
    .then(response => {
      item.streamingLink = response.result.link;
      return item;
    })
});

console.log(items_withLinks); // undefined

I have tried using await in different places and wrapping this in an async function but I can't figure out the right way to do it.

Upvotes: 0

Views: 203

Answers (2)

Robin Zigmond
Robin Zigmond

Reputation: 18249

The fundamental problem is that the function you are using in the .map doesn't return anything. (So you will actually technically get an array of undefined values, rather than undefined itself - but that obviously is no good.)

You need to return the promise and then use Promise.all to get the array of results.

// get array from database
const items = await client.db('database').collection('collection').find({}).toArray();

// for each object get and replace streamingLink
let items_withLinks = items.map((item) => {
  // return is the only thing I've added here!
  return getStreamingLink(item.filename) // API call to get link
    .then(response => {
      item.streamingLink = response.result.link;
      return item;
    })
});

const result = await Promise.all(items_withLinks);
console.log(result);

Upvotes: 1

The Fool
The Fool

Reputation: 20448

You can loop over your array and create a promise for each item. Then you can call Promise.all.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]

Upvotes: 2

Related Questions