Отобразите ответ Axios и добавьте ответ 2nd Axios к 1st - PullRequest
1 голос
/ 01 ноября 2019

Я создаю приложение React для поиска фильмов с использованием axios и API TMDb. Я хочу сделать axios.get вызов для поиска фильма на основе query, затем сопоставить ответ и передать movie.id для каждого фильма во второй axios вызов, чтобы получить больше деталей для каждого фильма.

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

Я думал, что это будетПроще сделать мой первый вызов axios внутри моей функции поиска, а затем написать вторую функцию getDetails(id), которая принимает идентификатор фильма и выполняет с ним вызов axios.

В идеале, если я вызову функцию getDetails на карте, получу ответ, добавлю этот ответ к моему массиву фильмов, я мог бы легко иметь массив фильмов с добавленными деталями к каждому отдельному фильму. Затем я мог бы сохранить весь массив в состоянии и использовать один фрагмент состояния для управления всеми данными моего фильма. Я знаю, что этот процесс не является синхронным, и что аксиозы основаны на обещаниях, но есть ли способ сделать это последовательно или я все неправильно подхожу? Я знаю, что .push() не работает в этой ситуации, но я пробовал другие методы, и они всегда возвращали неопределенный результат, обещание или непредвиденный результат.

 const search = query => {
    axios
      .get(
        `https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
      )
      .then(response => {
        response.data.results.map(movie => {
          const details = getDetails(movie.id);
          return movie.push(details);
        });
      });
  };

  const getDetails = id => {
    axios
      .get(
        `https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
      )
      .then(response => {
        return response.data;
      });
  };

РЕДАКТИРОВАТЬ 1: Я играл с ответом Abanoub Istfanous, и он, кажется, вернулся неопределенным с добавленной отправкой, чтобы обновить мое состояние. Я настроил его больше, и второй набор кода, помеченный как WORKING, похоже, отображает некоторые результаты поиска, но я не могу отобразить любые добавленные данные из getDetails на экран, так как они показывают неопределенные. Я все еще что-то делаю неправильно?

НЕ РАБОТАЕТ:

  const search = async query => {
    dispatch({
      type: MOVIE_SEARCH_REQUEST
    });
    const response = await axios.get(
      `https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
    );

    const data = Promise.all(
      response.data.results.map(async movie => {
        movie.details = await getDetails(movie.id);
      })
    );

    dispatch({
      type: MOVIE_SEARCH_COMPLETE,
      payload: data
    });
    return data;
  };

// getDetails is unchanged...

РАБОТАЕТ:


  const search = async query => {
    dispatch({
      type: MOVIE_SEARCH_REQUEST
    });
    const response = await axios.get(
      `https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
    );

    const data = Promise.all(
      response.data.results.map(async movie => {
        movie.details = await getDetails(movie.id);
      })
    );

    dispatch({
      type: MOVIE_SEARCH_COMPLETE,
      payload: response.data.results
    });
    return data;
  };

// getDetails is unchanged...

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Рекомендую использовать Promise

/*
*@return data 
*/
const getDetails = async (id) => {
    const response =  await axios
      .get(
        `https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
      )
      return response.data
  };


, затем

 const search = async (query) => {
    const response = await axios
      .get(
        `https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
      );
const data = Promise.all(response.data.results.map(async movie => {

  movie.details = await getDetails(movie.id);
}))
return data

  };


0 голосов
/ 01 ноября 2019

Причина, по которой он возвращает неопределенное, заключается в том, что Promise.all () будет выполняться асинхронно в очереди заданий и будет возвращать результат только после того, как весь Javascript будет выполнен и стек вызовов опустеет. Таким образом, простое решение для вашего кода будет помещать ожидание перед Promise.all ().

const search = async query => {
dispatch({
  type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
  `https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);

const data = await Promise.all(
  response.data.results.map(async movie => {
    movie.details = await getDetails(movie.id);
  })
);

dispatch({
  type: MOVIE_SEARCH_COMPLETE,
  payload: response.data.results
});
return data; //No need to return data since you are dispatching it to redux store
};

Подробнее об асинхронной природе JS в браузерах вы можете прочитать здесь:

https://medium.com/@Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd

...