Node.js中Spotify Web API异步调用顺序问题及解决方法
搞定Spotify API异步执行顺序问题
哥们,你踩中了Node.js异步编程的经典坑——你的authorize()是异步函数,但你调用它的时候没等它跑完,后面的API请求直接就冲出去了,这时候access token还没设置好,请求肯定失败啊!
别慌,咱们一步步改,核心就是确保setAccessToken执行完再调用后续API,具体方案如下:
核心修改点:用await等待异步授权完成
因为authorize()是async函数,它内部的await spotifyApi.authorizationCodeGrant(code)是异步操作,你直接调用authorize()的话,它会立刻返回一个Promise,代码会继续往下走,根本不等授权和token设置完成。
所以我们需要做两个关键修改:
- 把路由回调函数改成
async函数:这样才能在回调里使用await关键字; - 用
await等待authorize()执行完毕:让代码暂停在这里,等token设置好再继续执行后续API请求。
修改后的完整代码
app.get('/callback', async (req, res) => { // 改成async函数 var code = req.query.code || null; if (code === null) { console.log("code is null"); } async function authorize() { const data = await spotifyApi.authorizationCodeGrant(code); accesToken = data.body['access_token']; // 这里注意拼写,是不是应该是accessToken? refreshToken = data.body['refresh_token']; spotifyApi.setAccessToken(accesToken); spotifyApi.setRefreshToken(refreshToken); } try { await authorize(); // 这里加await,等待授权和token设置完成 } catch (err) { console.log('Something went wrong during authorization!', err); return res.redirect('/error'); // 可以加个错误跳转,避免继续执行后面的代码 } // 现在这里的API请求肯定能拿到已设置好的access token了 spotifyApi.getMySavedTracks({ limit : lim, offset: 1 }) .then(function(data) { return data.body.items; }, function(err) { console.log('Failed to get saved tracks!', err); }) .then(function(items) { let ids = []; items.forEach(function(item) { ids.push(item.track.id); }) return spotifyApi.getAudioFeaturesForTracks(ids); }) .then(function(data) { let songs = data.body.audio_features; let filteredSongURIs = []; songs.forEach(function(song) { if ((song.energy >= moodScore-offset) && (song.energy <= moodScore+offset)) { filteredSongURIs.push(song.uri); } }) // 创建播放列表并添加歌曲 return spotifyApi.createPlaylist('Mooder Playlist', { 'description': 'My description', 'public': true }) .then(function(data) { return data.body.id; }, function(err) { console.log('Failed to create playlist!', err); }) .then(function(playlist) { return spotifyApi.addTracksToPlaylist(playlist, filteredSongURIs); }) .then(function(data) { console.log('Added tracks to playlist!'); }, function(err) { console.log('Failed to add tracks to playlist!', err); }); }, function(err) { console.log(err); }); res.redirect('/testAPI'); });
额外优化建议(可选)
如果你觉得链式then看起来有点绕,可以把整个API请求部分也改成async/await风格,代码会更清晰:
// 替换掉原来的链式then部分 try { // 获取收藏的歌曲 const savedTracksData = await spotifyApi.getMySavedTracks({ limit : lim, offset: 1 }); const items = savedTracksData.body.items; // 提取歌曲ID const ids = items.map(item => item.track.id); // 获取音频特征 const audioFeaturesData = await spotifyApi.getAudioFeaturesForTracks(ids); const songs = audioFeaturesData.body.audio_features; // 过滤符合条件的歌曲 const filteredSongURIs = songs.filter(song => song.energy >= moodScore - offset && song.energy <= moodScore + offset ).map(song => song.uri); // 创建播放列表 const playlistData = await spotifyApi.createPlaylist('Mooder Playlist', { 'description': 'My description', 'public': true }); const playlistId = playlistData.body.id; // 添加歌曲到播放列表 await spotifyApi.addTracksToPlaylist(playlistId, filteredSongURIs); console.log('Added tracks to playlist!'); } catch (err) { console.log('API request failed!', err); }
这样代码的执行顺序一目了然,错误处理也更集中。
关键知识点回顾
async函数总是返回一个Promise;await关键字只能在async函数内部使用,它会暂停代码执行,直到后面的Promise完成;- 异步操作如果不等待,代码会按顺序继续执行,导致依赖异步结果的后续操作出错。
内容的提问来源于stack exchange,提问作者Khashhogi
相关产品推荐
相关产品推荐

