开发者问题收集

Android 应用程序可能出现未处理的承诺拒绝

2021-11-23
4128

我这几天一直在练习 React Native。我正在尝试制作一个电影页面应用程序。我的代码可以正常工作。但我的问题是它显示了一个关于可能未处理的承诺拒绝的错误。我知道问题出在哪里,但我不知道如何修复它。

这里是问题的根源(Details.js):

import { isEmptyStatement } from '@babel/types';
import React, {useEffect, useState} from 'react';
import {Text} from 'react-native';
import {getMovie, getTv} from '../services/services';

const Detail = ({route, navigation}) => {
    const movieId = route.params.movieDetail.id;

    const [movieDetail, setMovieDetail] = useState([]);
    const [movieTv, setMovieTv] = useState([]);
    
    const [loaded, setLoaded] = useState(false);
    const [success, setSuccess] = useState(false);

    useEffect(() => {
        getMovie(movieId).then(movieData => {
            if(movieData == null) {
                setLoaded(false);
            }
            else {
                setMovieDetail(movieData);
                setLoaded(true);
            }
        });
    }, [movieId]);
    
    useEffect(() => {
        getTv(movieId).then(movieTv => {
            if(movieTv == null) {
                setLoaded(false);
            }
            else {
                setMovieTv(movieTv);
                setLoaded(true);
            }
        });
    }, [movieId]);

    if(movieDetail.title == null){
        return (
            <React.Fragment>
                {loaded && <Text>{movieTv.name}</Text>}
            </React.Fragment>
        );
    }
    else {
        return (
            <React.Fragment>
                {loaded && <Text>{movieDetail.title}</Text>}
            </React.Fragment>
        );
    }

    console.log(movieTv.success);
    
}

export default Detail;

这是他们获取数据的地方(services.js):

import axios from 'axios';

const apiUrl = 'https://api.themoviedb.org/3';
const apiKey = 'api_key=31a7f8174b1e2c29744ec644af796973';

// Get Popular Movies
export const getPopularMovies = async () => {
    const resp = await axios.get(`${apiUrl}/movie/popular?${apiKey}`,);
    return resp.data.results;
};

// Get Upcoming Movies
export const getUpcomingMovies = async () => {
    const resp = await axios.get(`${apiUrl}/movie/upcoming?${apiKey}`,);
    return resp.data.results;
};

// Get Popular TV
export const getPopularTv = async () => {
    const resp = await axios.get(`${apiUrl}/tv/popular?${apiKey}`,);
    return resp.data.results;
};

export const getFamilyMovies = async () => {
    const resp = await axios.get(`${apiUrl}/discover/movie?${apiKey}&with_genres=10751`,);
    return resp.data.results;
};

export const getMovie = async id => {
    const resp = await axios.get(`${apiUrl}/movie/${id}?${apiKey}`,);
    return resp.data;
};

export const getTv = async id => {
    const resp = await axios.get(`${apiUrl}/tv/${id}?${apiKey}`,);
    return resp.data;
};
1个回答

您已在 Details.js 类中使用了多个异步调用并处理了返回的承诺。但在每种情况下,您仅通过提供 then 回调来处理成功(承诺解析)路径。

例如,请考虑此

getTv(movieId).then(movieTv => {
    if(movieTv == null) {
        setLoaded(false);
    }
    else {
        setMovieTv(movieTv);
        setLoaded(true);
    }
});

在这里,您的应用程序将运行良好, 只要网络调用成功并且后端返回成功(例如 2xx)响应 。但是,如果发生任何错误,您的应用程序将崩溃,因为您没有通过处理承诺拒绝来处理错误。

因此,您应该向每个承诺添加一个 catch 回调,并妥善处理错误情况。您可以执行诸如记录错误、设置任何标志以指示加载失败、在 UI 上显示错误等操作。

getTv(movieId).then(movieTv => {
    if(movieTv == null) {
        setLoaded(false);
    }
    else {
        setMovieTv(movieTv);
        setLoaded(true);
    }
}).catch(err => {
  console.log(err);
  setLoaded(false);
});
Udith Gunaratna
2021-11-23