Сделайте несколько вызовов API после вызова API - PullRequest
0 голосов
/ 23 июня 2019

Я пытаюсь перебрать список URL-адресов, поступающих из вызова API. Как я могу сделать этот код синхронным?

Я уже пытался использовать async / await перед итерациями .map (), но он всегда переходит к функции диспетчеризации.

  return dispatch => {
    let query = `?`;
    if (currentPage) query += `page=${currentPage}`;
    if (isAlive) query += `&isAlive=${isAlive}`;
    if (name) query += `&name=${name}`;
    dispatch(fetchCharsStart());
    axios
      .get(`https://www.anapioficeandfire.com/api/characters${query}`)
      .then(({ data }) => data)
      .then(characters => {
        //Iterating all characters
        characters.map(char => {
          char.fetchedBooks = [];
          //Iterating books for each character...
          char.books.map(url => {
            axios.get(url).then(({ data }) => {
              console.log("Fetching...");
              char.fetchedBooks.push({
                name: data.name,
                release: data.release
              });
            });
          });
        });
        console.log("Characters: ", characters);
        dispatch(fetchCharsSuccess(characters));
      })
      .catch(err => {
        console.log(err);
        dispatch(fetchCharsFail(err));
      });
  };
};

Я ожидал, что журнал fetchChars () будет Fetching... 15 раз и только после этого - массив символов, но я получаю противоположное поведение.

Ответы [ 2 ]

0 голосов
/ 23 июня 2019
export const fetchChars = (currentPage, isAlive, name) => {
return dispatch => {
let query = `?`;
if (currentPage) query += `page=${currentPage}`;
if (isAlive) query += `&isAlive=${isAlive}`;
if (name) query += `&name=${name}`;
dispatch(fetchCharsStart());
axios
  .get(`https://www.anapioficeandfire.com/api/characters${query}`)
  .then(({ data }) => {
    return data;
  })
  .then(async characters => {
    //Iterating all characters
    for (let i = 0; i < characters.length; i++) {
      characters[i].fetchedBooks = [];
      //Iterating books for each character...
      for (let j = 0; j < characters[i].books.length; j++) {
        await axios.get(characters[i].books[j]).then(({ data }) => {
          console.log("Fetching...");
          characters[i].fetchedBooks.push({
            name: data.name,
            release: data.release
          });
        });
      }
    }

    console.log("Characters: ", characters);
    dispatch(fetchCharsSuccess(characters));
  })

Я решил использовать циклы for..Map () создавал дополнительные функциональные области, и ничто не указывало функции then ждать завершения запросов.Теперь, поскольку циклы for не создают функциональных областей, ключевое слово async будет в той же области, что и ключевое слово await.

0 голосов
/ 23 июня 2019

Это ожидаемое поведение: вы зацикливаетесь на асинхронном запросе, но не решаете все обещания перед выполнением следующего кода, поэтому вы регистрируете «Characters..." перед извлечением всех ваших данных.

Вы былина хорошем пути, когда вы пытались async/await.

getCharacters = async () => {
    let res = await axios.get(`https://www.anapioficeandfire.com/api/characters${query}`);
    ...
    ...
    return characters;
};

Вы должны объединить свои запросы в асинхронную / ожидающую очередь, чтобы все ваши обещания были выполнены до того, как вы выполните остальную часть кода.

let characters = await getCharacters();

characters.map(char => {
    char.fetchedBooks = [];
    //Iterating books for each character...
    char.books.map(url => {
      let books = await getBooks();
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...