我正在使用 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]);
我认为问题在于流派的异步获取,因为地图迭代器在继续之前不会等待 api 调用返回。
我建议将 res.body.items.map 更改为 for 循环,并在 fetchArtistGenres 调用中使用await 运算符。这将在等待返回艺术家流派时暂停循环。
Await 可以在地图迭代器中使用,但它不会暂停循环,而是返回一个承诺,您的代码将需要大量重构来支持这种方法。
我发现this文章有助于理解循环中的异步调用。