Проблемы с асинхронностью / ожиданием — Как ждать запросов

#javascript #node.js #async-await

Вопрос:

У меня есть массив объектов, содержащих метаданные для видео. Мне нужно повторить его, и для каждого объекта мне нужно выполнить вызов API, передающий его filename , чтобы получить a streamingLink и назначить его объекту streamingLink . Моя проблема в том, что к тому времени, когда я возвращаю этот массив, массив не определен. Как мне сообщить коду, чтобы он подождал, пока streamingLink не будет назначен?

Вот как выглядит мой код:

 // 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 

Я пробовал использовать await в разных местах и оборачивать это в async функцию, но я не могу понять, как это правильно сделать.

Ответ №1:

Вы можете перебирать свой массив и создавать обещание для каждого элемента. Тогда ты можешь позвонить Обещанию.все.

 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"]
 

Ответ №2:

Основная проблема заключается в том, что функция, которую вы используете в .map , ничего не возвращает. (Таким образом, вы фактически технически получите массив undefined значений, а не undefined сами по себе, но это, очевидно, никуда не годится.)

Вам нужно return обещание, а затем использовать Promise.all его для получения массива результатов.

 // 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);
 

Комментарии:

1. Блестящий. Спасибо!!