React中如何等待异步函数执行结果并正确获取接口返回数据?
问题根因
两个核心错误导致这个现象:
- 异步执行时序问题:
facultiesService.getAllFaculties()是异步请求,传入.then()的回调会在请求响应返回后才被加入事件队列执行,但回调外的console.log(faculties)、faculties.map是同步代码,会在请求发出后立刻执行,这时候响应还没回来,faculties自然还是初始的空数组。 - 违反React渲染规则:你用普通局部变量存需要驱动视图更新的数据,一方面普通变量在每次组件重渲染时都会重置为初始值,另一方面修改变量不会触发组件重渲染,就算异步回调里给变量赋了值,组件也不会重新执行渲染逻辑拿到新值。
你之前把showOptions改成async函数会报错,是因为async函数默认返回Promise对象,React渲染时不会等待Promise resolve,会直接把Promise当合法JSX节点渲染,自然抛错。
修复方案
用React内置的状态管理存储接口数据,在组件挂载阶段发起请求,请求返回后更新状态,状态变更会自动触发组件重渲染,这时候就能拿到最新的列表渲染选项。
参考修复代码:
import { useState, useEffect } from 'react'; // 保留你原有的其他依赖导入,比如Form组件、facultiesService // 在你的函数组件内部定义状态和请求逻辑 const [faculties, setFaculties] = useState([]); const [loading, setLoading] = useState(false); // 组件挂载时拉取学院列表 useEffect(() => { const getFacultyList = async () => { setLoading(true); try { const resp = await facultiesService.getAllFaculties(); // 注意:常规接口请求返回的resp.data是普通数组/对象,不是Promise,不需要额外await setFaculties(resp.data); } catch (e) { console.log('获取学院列表失败:', e); } finally { setLoading(false); } }; getFacultyList(); }, []); // 渲染选项逻辑直接读取状态即可 const showOptions = () => { if (loading) { return <option disabled>加载中...</option> } return faculties.map(faculty => ( <option key={faculty.id} value={faculty.id} > {faculty.name} </option> )); } const showFacultySelect = () => { return ( <Form.Select aria-label="Default select example"> {showOptions()} </Form.Select> ) }
注意事项
- 不要在直接参与渲染的函数(比如你原来写的
showOptions)里直接发异步请求,会导致重复触发请求、渲染时序错乱,数据请求逻辑要放到useEffect或者用户事件回调里 - 所有需要驱动视图更新的数据都要存在state里,不要用普通局部变量/全局变量存这类数据,修改变量不会触发React重渲染
- 如果你的接口封装返回的
resp.data本身是Promise(极少见),才需要加await,常规axios类请求封装不需要这一步 - 加上加载状态可以避免用户看到空下拉框的异常体验
内容的提问来源于stack exchange,提问作者Enchantres
相关产品推荐
相关产品推荐

