如何在ReactJS中的UseEffect中等待api调用?

问题描述 投票:0回答:1

我正在使用 useEffect 进行 api 调用,并且在承诺的解析范围内,我正在进行另一个 api 调用,但我似乎存在一些异步问题,即在设置必要参数之前创建对象。创建我的 Song 对象之前的 console.log 在嵌套承诺的解析中的 console.logs 之前打印。我怎样才能让我的代码以正确的顺序执行?

class Song {
    constructor(id, title, artists, genres) {
        this.id = id;
        this.title = title;
        this.artists = artists;
        this.genres = genres;
    }
}

export default function Dashboard({ code }) {
    const accessToken = useAuth(code);
    const [songs, setSongs] = useState([]);
    console.log(songs);

    useEffect(() => {
        var genres;
        const fetchArtistGenres = async (artistId) => {
            await spotifyApi.getArtist(artistId).then((res) => {
                console.log("GENRES FROM FETCH FUNCTION", res.body.genres);
                return res.body.genres;
            });
        };
        if (accessToken) {
            spotifyApi.getMySavedTracks({ limit: 2 }).then((res) => {
                setSongs(
                    res.body.items.map((item) => {
                        const artists = item.track.artists.map((artist) => {
                            return {
                                name: artist.name,
                                id: artist.id,
                            };
                        });

                        if (!item.track.genres) {
                            // make call to artist endpoint
                            fetchArtistGenres(artists[0].id)
                                .then((res) => {
                                    genres = res;
                                    console.log("GENRES FROM PROMISE", res);
                                })
                                .catch((err) => {
                                    console.log(err);
                                });
                        } else {
                            genres = item.track.genres;
                        }
                        console.log("genres before creating song: " + genres);

                        return new Song(
                            item.track.id,
                            item.track.name,
                            artists,
                            genres
                        );
                    })
                );
            });
        }
    }, [accessToken]);
reactjs async-await
1个回答
1
投票

我认为问题在于流派的异步获取,因为地图迭代器在继续之前不会等待 api 调用返回。

我建议将 res.body.items.map 更改为 for 循环,并在 fetchArtistGenres 调用中使用await 运算符。这将在等待返回艺术家流派时暂停循环。

Await 可以在地图迭代器中使用,但它不会暂停循环,而是返回一个承诺,您的代码将需要大量重构来支持这种方法。

我发现this文章有助于理解循环中的异步调用。

© www.soinside.com 2019 - 2024. All rights reserved.