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

React组件中异步函数始终返回Promise {<pending>}问题求助

问题:Next.js函数组件中异步函数返回Promise {<pending>}

我在Next.js的React函数式组件里运行异步函数,不管怎么操作,函数都返回Promise {<pending>}。调用模拟API时正常,但这次需要从getServerSideProps获取access_token,不确定是不是这个原因导致的。另外,在函数内部用console.log能拿到正确结果,但用return就不行。

相关代码

异步函数checkLoved

const checkLoved = async (id: string) => {
  try {
    const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
      headers: {
        Authorization: `Bearer ${test.access_token}`,
      },
    });

    const data = await response.json();

    return data[0];
  } catch (error) {
    console.error(error);
  }
};

getServerSideProps代码

export async function getServerSideProps(context) {
  const session = await getSession(context);

  if (!session) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    };
  }

  const {
    token: { accessToken },
  } = session;

  const test = await getAccessToken(accessToken);

  return {
    props: { test, accessToken },
  };
}

目标实现代码

const Discover: NextPageWithLayout = ({ test }: IDiscover) => {
  const checkLoved = async (id: string) => {
    try {
      const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
        headers: {
          Authorization: `Bearer ${test.access_token}`,
        },
      });

      const data = await response.json();

      return data[0];
    } catch (error) {
      console.error(error);
    }
  };

  const array = [{ test: 1 }, { test: 2 }];

  return (
    <div>
      {array.map((item) => {
        console.log();

        return <Component test={checkLoved('7jCy1opEtV4a0TnKrtsSdo')}>{item.test}</Component>;
      })}
    </div>
  );
};

解决方案

问题核心是异步函数本身就会返回Promise,直接在组件渲染时调用checkLoved,拿到的就是未resolved的Promise,而不是最终结果。和getServerSideProps获取access_token无关,是React渲染逻辑和异步函数的基础特性问题。

正确处理方式:React状态+useEffect

  1. 用useState存储异步请求的结果
  2. 用useEffect触发异步函数,更新状态
  3. 渲染时使用状态值,而非直接调用异步函数

修改后的代码示例:

import { useState, useEffect } from 'react';

const Discover: NextPageWithLayout = ({ test }: IDiscover) => {
  // 存储歌曲的收藏状态,用对象映射便于管理多个id
  const [lovedStatus, setLovedStatus] = useState<Record<string, boolean | null>>({});

  const checkLoved = async (id: string) => {
    try {
      const response = await fetch(`https://api.spotify.com/v1/me/tracks/contains/?ids=${id}`, {
        headers: {
          Authorization: `Bearer ${test.access_token}`,
        },
      });

      const data = await response.json();
      return data[0];
    } catch (error) {
      console.error(error);
      return false; // 出错时返回默认值
    }
  };

  // 组件挂载或access_token更新时,执行异步请求
  useEffect(() => {
    const fetchStatus = async () => {
      const targetId = '7jCy1opEtV4a0TnKrtsSdo';
      const status = await checkLoved(targetId);
      setLovedStatus(prev => ({ ...prev, [targetId]: status }));
    };

    fetchStatus();
  }, [test]);

  const array = [{ test: 1 }, { test: 2 }];

  return (
    <div>
      {array.map((item) => {
        const targetId = '7jCy1opEtV4a0TnKrtsSdo';
        // 处理加载状态
        if (lovedStatus[targetId] === null) {
          return <div>加载中...</div>;
        }
        return <Component test={lovedStatus[targetId]}>{item.test}</Component>;
      })}
    </div>
  );
};

为什么console.log能拿到正确结果?

在异步函数内部,await已经等待请求完成,console.log(data[0])是在Promise resolved之后执行的,但函数本身返回的依然是Promise,外部调用必须用await或.then()才能获取最终结果。

额外优化建议

  • 如果需要检查多个歌曲id,不要在map里重复调用异步函数,建议批量处理请求减少重复请求
  • 添加加载、错误状态提示,提升用户体验
  • 可以使用SWR或React Query这类数据请求库,简化异步状态管理逻辑

内容的提问来源于stack exchange,提问作者Kozak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:51:13