Создание объекта с несколькими асинхронными / ожидающими вызовами - PullRequest
0 голосов
/ 29 августа 2018

Я использую API, который имеет данные на двух конечных точках:

  • / news получает список статей, включающий небольшое количество свойств
  • / news / {id} / метаданные получают все свойства статьи

Мне действительно нужно получить все свойства, и я планирую построить главный объект для управления моим пользовательским интерфейсом.

Текущие функции:

  • getNews: асинхронная / ожидающая функция, которая успешно получает список статей из / news
  • getMetaPerArticle: еще одна асинхронная / ожидающая функция, которая принимает идентификатор и вызывает / news / {id} / метаданные

Поведение:

  • Я запускаю асинхронные функции getNews и жду ответа
  • при получении ответа я сопоставляю массив ответов и запускаю функцию getMetadata для каждого элемента массива
  • после завершения getMetadata результат сохраняется в константе и присваивается элементу .metadata

Задача : - обе мои функции разрешаются, но мой конечный объект содержит объекты Promise.resolve. Объекты имеют правильные значения.

Код

const getNews = async options => {
    try {
      const { data } = await axios(options);
      const parsedEnDataWithMeta = parsedEnData.map(article => {
        const mergedArticleWithMeta = {
          ...article,
          ...getMetaPerArticle(article.id)
        };
        return mergedArticleWithMeta;
      });
    } catch (getNewsError) {
      dispatch(receiveNewsError(getNewsError));
    }
  };



const getMetaPerArticle = async articleID => {
    const axiosOptions = {
      method: "GET",
      url: `url`,
    };
    try {
      const response = await axios(axiosOptions);
      return response.data;
    } catch (err) {
      console.error(err);
      dispatch(receiveNewsError(err));
    }
  };

Выход

(6) [{…}, {…}, {…}, {…}, {…}, {…}]
0: {
    abstract: "",
    ...
    metadata: Promise {<resolved>: {...}}
}

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Ваша проблема в том, что getMetaPerArticle возвращает Обещание, поэтому вам нужно добавить await вместо него и отметить функцию стрелки как async.

const parsedEnDataWithMeta = parsedEnData.map(async article => {
  const mergedArticleWithMeta = {
    ...article,
    ...await getMetaPerArticle(article.id)
  };
  return mergedArticleWithMeta;
});

После этого parsedEnDataWithMeta будет содержать список Обещаний, поэтому вам нужно будет подождать, пока все они не будут решены с помощью Promise.all:

const parsedEnDataWithMeta = await Promise.all(parsedEnData.map(async article => {
  const mergedArticleWithMeta = {
    ...article,
    ...await getMetaPerArticle(article.id)
  };
  return mergedArticleWithMeta;
}));

Если вам нужно использовать это чаще, вы можете определить функцию карты, которая будет обрабатывать обещания:

function promiseMap( array, callback ) {
  return Promise.all(array.map(callback))
}


const parsedEnDataWithMeta = await promiseMap(parsedEnData, async article => {
  const mergedArticleWithMeta = {
    ...article,
    ...await getMetaPerArticle(article.id)
  };
  return mergedArticleWithMeta;
});
0 голосов
/ 29 августа 2018

getMetaPerArticle возвращает обещание, поэтому вам нужно дождаться разрешения этих обещаний, прежде чем пытаться сопоставить parsedEnDataWithMeta. Примерно так:

const getNews = async options => {
  try {
    const { data } = await axios(options);
    const metadataPromises = data.map(article => getMetaPerArticle(article.id));
    const metadata = await Promise.all(metadataPromises);
    const parsedEnDataWithMeta = data.map((article, i) => ({
      ...article,
      ...metadata[i]
    });
  } catch (getNewsError) {
    dispatch(receiveNewsError(getNewsError));
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...