You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

返回空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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:33:48