Ожидание ответа API в цикле

Я перебираю массив и выполняю вызов REST API для каждого элемента, но у меня возникают проблемы с асинхронной природой js. Я пытаюсь использовать async/await, но не думаю, что настроил его правильно, потому что он не будет ждать ответа и возвращает неопределенное значение.

onSearchSuccess = async (response) => {
  const persons = response._embedded.persons_search_collection;
  const personsWithClasses = await persons.reduce(
  (acc, person) => {
    const params = {
      person_id: person.person_id,
      date: '2017-01-05',
      enrollment_status: 3,
      class_status: 2,
    };
    return getClasses( //this function does an GET request and returns the response
      params,
      (classesResponse) => {
        const { classes } = classesResponse._embedded;
        console.log(classes); //logs after the console.log below
        return [...acc, { ...person, classes }];
      },
      () => acc,
    );
  }, []);
console.log(personsWithClasses); //return undefined
}


export const getClasses = (params, success, error) => {
  axios.get(`${uri}/classes`, { params })
  .then(({ data }) => {
    success(data);
  })
  .catch(err => error(err));
};

1 ответ

Решение

Как я уже упоминал в комментариях, reduce не будет работать так, как вы хотите, если вы вызываете асинхронные функции. Ты можешь использовать Promise.all а также .map как так (я пытался использовать async/await как можно больше):

onSearchSuccess = async (response) => {
  const persons = response._embedded.persons_search_collection;
  let personsWithClasses = await Promise.all(persons.map(async (person) => {
    try {
      const classes = await getClasses({
        person_id: person.person_id,
        date: '2017-01-05',
        enrollment_status: 3,
        class_status: 2,
      });

      return {...person, classes};
    } catch(error) {
      // ignore errors if a person wasn't found
      return null;
    }
  }));
  personsWithClasses = personsWithClasses.filter(x => x != null);
  console.log(personsWithClasses);
}


export const getClasses = params => {
  return axios.get(`${uri}/classes`, { params });
};

Также обратите внимание на изменения, которые я внес в getClasses, Нет причин, чтобы он принимал обратные вызовы, если axios.get в любом случае возвращает обещание.

Другие вопросы по тегам