【发布时间】:2020-03-29 15:29:48
【问题描述】:
我在 React 中使用 Spotify API 闲逛,并且在为嵌套数据进行 api 调用时遇到了麻烦。我在 componentDidMount 中的计划是:
- 获取用户帐户数据
- 使用该帐户数据获取用户的播放列表
- 使用这些播放列表获取每个播放列表中的曲目
- 建立一个包含名称、ID 和曲目的播放列表对象
- 将播放列表对象推送到播放列表数组
- 使用用户帐户数据和播放列表数组设置状态
这是我的 componentDidMount 和获取播放列表曲目的方法:
async componentDidMount() {
const userResponse = await axios.get(`https://api.spotify.com/v1/me`, {
headers: {
Authorization: 'Bearer ' + this.state.access_token
}
});
const playlistsResponse = await axios.get(
`https://api.spotify.com/v1/users/${userResponse.data.id}/playlists`,
{
headers: {
Authorization: 'Bearer ' + this.state.access_token
}
}
);
let playlists = [];
playlistsResponse.data.items.map((playlist) => {
const tracks = this.getTracks(playlist.id);
let newPlaylist = {
name: playlist.name,
id: playlist.id,
tracks: tracks
};
playlists.push(newPlaylist);
});
this.setState({
playlists: playlists,
userData: userResponse.data
});
}
async getTracks(playlistID) {
const tracks = await
axios.get(`https://api.spotify.com/v1/playlists/${playlistID}/tracks`, {
headers: {
Authorization: 'Bearer ' + this.state.access_token
}
});
return tracks;
}
在渲染中控制台记录状态后,我看到我能够将 userData 设置为状态。我也可以设置播放列表,但是,只有 name 和 id 被传递,并且曲目被设置为 Promises。我是否在尝试在地图内调用曲目 API 以便一次构建播放列表对象 1 个?
更新:
所以我通过将我的地图回调分配为异步函数来让它工作。这是sn-p:
let playlists = [];
playlistsResponse.data.items.map(async (playlist) => {
const tracksResponse = await axios.get(`https://api.spotify.com/v1/playlists/${playlist.id}/tracks`, {
headers: {
Authorization: 'Bearer ' + this.state.access_token
}
});
let newPlaylist = {
name: playlist.name,
id: playlist.id,
tracks: tracksResponse
};
playlists.push(newPlaylist);
});
this.setState({
playlists: playlists,
userData: userResponse.data
});
}
这是一种公平的处理方式吗?对我来说,我在地图的每次迭代中等待 trackResponse 数据,然后在稍后构建我的播放列表对象时使用它是有道理的。将我的地图回调包装在 async/await 中是否安全/常见做法?
更新 2:
好吧,也许它不起作用。当我检查 Chrome devtools 时,我可以看到所有状态,但是当我尝试渲染状态时,什么都不会吐出。
【问题讨论】:
-
setState本质上是异步的。您需要等待tracks被获取,然后才能执行setState。 -
但是我如何等待曲目被获取?我想,因为我将 getTracks 设为异步函数,所以每次在我的地图中调用它时,它都会等待获取轨道,然后再返回它们。
-
你需要改变函数的顺序。最后移动
setState。还存储tracks的响应,就像您对播放列表和 userReposne 所做的那样。会更容易阅读。像这样:const tracksResponse = await getTracks -
setState 是 componentDidMount 内部的最后一个,getTracks 是我在 componentDidMount 外部定义的方法
-
我认为你误解了异步等待。例如,在您的函数
getTracks中,async await 将用于在解析完成后返回。它不能用作回调
标签: reactjs async-await axios