Axios не публикует массив

#javascript #arrays #reactjs #json #axios

Вопрос:

У меня есть приложение React, которое отправляет данные в мой пользовательский API-интерфейс Flask.

 const params = {
            id: this.props.user.uid,
            title: movie.title,
            movie_id: parseInt(movie.id, 10),
            photo: "https://image.tmdb.org/t/p/w500/"   movie.backdrop_path,
            year: parseInt(movie.release_date.split("-")[0], 10),
            rating: parseInt(parseFloat(movie.vote_average) * 10, 10),
            overview: movie.overview,
            genres: genres
        };
 

Когда я распечатываю params.genres его, на нем появляется что-то вроде этого ["Fantasy", "Comedy"] .
Но когда я опубликую это:
axios.post("http://localhost:5000/user", params).then((data) => {
Полезная нагрузка составляет:
{"id":"id","title":"The Watch","movie_id":80035,"photo":"urltoimage","year":2012,"rating":55,"overview":"overview","genres":[]}

Все значения верны, за исключением жанров. И в моем бэкэнде написано то же самое. Что случилось?

Вся моя функция:

 addMovie(movie) {
        //get more data from tmdb
        var genres = [];
        axios
            .get(
                "https://api.themoviedb.org/3/movie/"  
                    parseInt(movie.id, 10),
                {
                    params: {
                        api_key: "dontsteelmytmdbkey;)",
                    },
                }
            )
            .then((req) => {
                for (let i = 0; i < req.data.genres.length; i  ){
                    genres.push(req.data.genres[i].name);
                }
            });
        console.log(genres);
        const params = {
            id: this.props.user.uid,
            title: movie.title,
            movie_id: parseInt(movie.id, 10),
            photo: "https://image.tmdb.org/t/p/w500/"   movie.backdrop_path,
            year: parseInt(movie.release_date.split("-")[0], 10),
            rating: parseInt(parseFloat(movie.vote_average) * 10, 10),
            overview: movie.overview,
            genres: genres
        };
        console.log(params.genres);
        axios.post("http://localhost:5000/user", JSON.stringify(params)).then((data) => {
            if (data.data.code === 112) {
                // success alert
                console.log("success alert");
                // remove movie from list
                let newMovies = this.state.movies;
                for (let i = 0; i < newMovies.length; i  ) {
                    if (newMovies[i].id === movie.id) {
                        newMovies.splice(i, 1);
                    }
                }
                this.setState({ movies: newMovies });
            } else {
                console.log("Backend error");
                console.log(
                    "Error: "   data.data.code   " - "   data.data.errno
                );
                this.setState({
                    showAlert: true,
                    alertSeverity: "error",
                    alertText: this.state.alertServerError,
                });
            }
        });

        // dont redirect
        //this.props.history.push("/");
    }
 

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

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

2. Я загрузил всю свою функцию добавления

3. Оба console.log(genres) и console.log(params.genres) возвращают множество жанров, как я уже говорил ранее

Ответ №1:

Эти вызовы axios в данный момент оба асинхронны, и они не ждут, пока друг друга урегулируют. Попробуйте изменить свой код таким образом, чтобы дождаться разрешения первого вызова, а затем выполнить цикл по жанрам.

 // add async to function definition 
async function addMovie(movie) {
  // get more data from tmdb
  const genres = [];
  try {
    const response = await axios.get('https://api.themoviedb.org/3/movie/'   parseInt(movie.id, 10), {
      params: {
        api_key: 'dontsteelmytmdbkey;)',
      },
    });

    for (let i = 0; i < response.data.genres.length; i  ) {
      genres.push(response.data.genres[i].name);
    }
  } catch (error) {
    console.error(error);
  }
  console.log(genres);
  const params = {
    id: this.props.user.uid,
    title: movie.title,
    movie_id: parseInt(movie.id, 10),
    photo: 'https://image.tmdb.org/t/p/w500/'   movie.backdrop_path,
    year: parseInt(movie.release_date.split('-')[0], 10),
    rating: parseInt(parseFloat(movie.vote_average) * 10, 10),
    overview: movie.overview,
    genres: genres,
  };
  console.log(params.genres);
  axios.post('http://localhost:5000/user', JSON.stringify(params)).then((data) => {
    if (data.data.code === 112) {
      // success alert
      console.log('success alert');
      // remove movie from list
      let newMovies = this.state.movies;
      for (let i = 0; i < newMovies.length; i  ) {
        if (newMovies[i].id === movie.id) {
          newMovies.splice(i, 1);
        }
      }
      this.setState({ movies: newMovies });
    } else {
      console.log('Backend error');
      console.log('Error: '   data.data.code   ' - '   data.data.errno);
      this.setState({
        showAlert: true,
        alertSeverity: 'error',
        alertText: this.state.alertServerError,
      });
    }
  });

  // dont redirect
  // this.props.history.push("/");
}
 

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

1. Спасибо за заявление о попытке.

Ответ №2:

 var genres = [];
        const res = await axios
            .get(
                "https://api.themoviedb.org/3/movie/"  
                    parseInt(movie.id, 10),
                {
                    params: {
                        api_key: "dontsteelmytmdbkey;)",
                    },
                }
            )
            
            for (let i = 0; i < res.data.genres.length; i  ){
                    genres.push(res.data.genres[i].name);
            }
 

Сделайте вашу функцию addMovie асинхронной, используйте ключевое слово async перед функцией addMovie.

зачем вам это нужно? потому что вам нужно подождать, пока ответ axios не разрешится.

для лучшего понимания вы можете прочитать больше об асинхронном ожидании

Ответ №3:

Он не ждет выполнения вызова API, который вы должны использовать асинхронно и ждать. Я добавил код ниже:

 addMovie(movie) async {
    //get more data from tmdb
    var genres = [];
    await axios
        .get(
            "https://api.themoviedb.org/3/movie/"  
                parseInt(movie.id, 10),
            {
                params: {
                    api_key: "dontsteelmytmdbkey;)",
                },
            }
        )
        .then((req) => {
            for (let i = 0; i < req.data.genres.length; i  ){
                genres.push(req.data.genres[i].name);
            }
        });
    console.log(genres);
    const params = {
 

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

1. Это неправильный способ дождаться разрешения запроса, асинхронность должна быть до того, как цепочка обратного вызова ключевого слова функции и ожидание не будут работать таким образом, я думаю, что этот ответ не должен быть помечен как принятый

2. у меня нет привилегий редактировать или комментировать ваш ответ, но ваш код в конечном итоге нарушит код, если запрос не будет обработан или из-за проблемы с сервером. вам нужно будет добавить вызов api в блок try catch.