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
- 用
useState存储异步请求的结果 - 用
useEffect触发异步函数,更新状态 - 渲染时使用状态值,而非直接调用异步函数
修改后的代码示例:
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
相关产品推荐
相关产品推荐

