返回空JSON问题:React客户端获取Spotify歌曲列表失败
问题排查与修复方案
我来帮你搞定这个问题——核心原因是异步操作的执行顺序没处理对,导致你还没等数据库的findOrCreate操作完成,就把空数组返回给客户端了。
问题根源分析
你的后端代码里,Song.findOrCreate是异步操作(返回Promise),但你在for循环里直接调用它后,没有等待这些异步操作全部完成,就立刻执行了console.log和res.json(songs)。这时候songs数组还没被任何数据填充,自然返回空数组。
至于你说的全量版本能工作,大概率是因为循环请求Spotify API时用了异步等待(比如await),间接让后续的数据库操作有时间完成,但这是偶然的,不是正确的异步处理方式。
后端代码修复(核心改动)
我们用async/await+Promise.all来确保所有异步操作完成后再返回结果:
// 假设这是你的路由处理函数,改成async函数 app.get('/mysongs', async (req, res) => { try { // 1. 调用Spotify API,等待响应并解析JSON const spotifyResponse = await fetch("https://api.spotify.com/v1/me/tracks", { method: "GET", headers: { Authorization: "Bearer " + req.user.accessToken } // 注意:fetch不支持`json: true`这个参数,解析JSON靠后续的res.json() }); const apiResponse = await spotifyResponse.json(); // 2. 把每个track转换成findOrCreate的Promise const songPromises = apiResponse.items.slice(0, apiResponse.limit).map(item => { const track = item.track; return Song.findOrCreate({ where: { name: track.name, song_spotify_id: track.id, album: track.album.name, popularity: track.popularity, track_number: track.track_number, uri: track.uri } }); }); // 3. 等待所有Promise完成,拿到完整的歌曲数组 const songs = await Promise.all(songPromises); console.log("songs: *********************", songs); res.status(200).json(songs); } catch (error) { console.error("获取歌曲失败:", error); res.status(500).json({ type: "ERROR ON FETCH", api_response: { success: false } }); } });
关键改动点:
- 用
async/await替代链式then,让异步逻辑更线性、易读 - 用
map生成所有findOrCreate的Promise,再通过Promise.all等待全部完成,确保songs数组被填满后再返回 - 移除了fetch里无效的
json: true参数 - 把错误处理统一放在
try/catch里,确保错误能正确返回给客户端
React端代码优化(可选)
你的前端代码本身没问题,但可以加一些错误处理和简化逻辑:
const requestMySongs = async () => { try { const response = await fetch("/mysongs"); // 检查请求是否成功(比如401、500等状态码) if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const jsoned = await response.json(); // 用slice替代for循环,更简洁地取前5首 const fiveSongs = jsoned.slice(0, 5); console.log(fiveSongs); return fiveSongs; } catch (error) { console.error("获取歌曲列表出错:", error); // 出错时返回空数组或提示用户 return []; } };
总结
本质问题就是没有等待异步操作完成就返回结果,Promise.all是处理多个异步任务的标准方案,能确保所有操作都结束后再继续后续逻辑。之前全量版本的“偶然成功”只是因为异步流程被间接阻塞,不是正确的处理方式。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

