为何useEffect钩子中异步函数无法返回结果?
异步API调用无返回结果排查
问题描述
我有如下API:
public async getWizardItem( userId, type, signal, ) { const axiosInstance = await this.axios; return axiosInstance .get(`${this.BASE_URL}/wizardStepItems/${userId}/${type}`, { signal }) .then(({ data }) => data); }
以下是调用该API的组件代码:
const AddWizardItemContainer = ({ outcome, classes, transitionDelay }: any) => { const userId = useUserId(); const [outcomeItemCount, setOutcomeItemCount] = useState<number>(0); const testFilter = useCallback( async (outcome) => { const response = await tpService.getWizardItem( userId, getWizardItemGetPayload( outcome.parameters?.wizardScreenName as MigraineWizardSuggestionScreen ) // abortController.current.signal ); console.log(response) //==NOT WORKING== const filteredResponse = filterItems( response, outcome.parameters.items, userId ); return filteredResponse.length; }, [userId] ); useEffect(() => { console.log('hello'); const response = testFilter(outcome); response.then((res) => { console.log(res); }); }, [outcome.parameters.items.length, outcome, testFilter]); return ( ... ); };
如上述代码所示,我尝试在useEffect中通过console.log输出结果,但仅能看到'hello',无法获取异步函数返回的结果,请问这是什么原因?
问题原因分析
- 未处理Promise异常:
testFilter是异步函数,返回的Promise如果因API请求失败、参数错误或内部代码报错被reject,但代码只调用了.then未添加.catch,错误会被静默吃掉,既看不到结果也看不到错误日志。 - API调用参数异常:
getWizardItemGetPayload的入参outcome.parameters?.wizardScreenName可能为undefined,导致生成的type参数不符合后端API要求,触发请求失败;另外API定义的第三个参数signal被注释,若后端要求该参数或axios因缺失signal出现异常,也会导致请求失败。 - useCallback依赖缺失:
testFilter的依赖数组仅包含userId,但函数内部用到了getWizardItemGetPayload和filterItems,若这两个函数有状态依赖且发生变化,testFilter不会更新,可能调用旧版本函数引发异常。
解决方案
添加错误捕获逻辑
在useEffect和testFilter内部添加错误捕获,排查具体报错信息:// useEffect中添加catch useEffect(() => { console.log('hello'); testFilter(outcome) .then((res) => { console.log(res); }) .catch((err) => { console.error('请求或处理失败:', err); }); }, [outcome.parameters.items.length, outcome, testFilter]); // testFilter内部添加try-catch const testFilter = useCallback( async (outcome) => { try { const payload = getWizardItemGetPayload( outcome.parameters?.wizardScreenName as MigraineWizardSuggestionScreen ); console.log('API请求type参数:', payload); // 打印参数确认合法性 const response = await tpService.getWizardItem( userId, payload, // 若signal必填,需创建AbortController传入 // new AbortController().signal ); console.log(response); const filteredResponse = filterItems( response, outcome.parameters.items, userId ); return filteredResponse.length; } catch (err) { console.error('testFilter执行出错:', err); throw err; // 抛出错误让上层捕获 } }, [userId, getWizardItemGetPayload, filterItems] // 补全缺失的依赖 );校验API调用参数
打印getWizardItemGetPayload的返回值,确认type参数符合后端要求;若signal为必填项,需创建AbortController并传入对应signal(同时注意在组件卸载时终止请求,避免内存泄漏)。补全useCallback依赖
将getWizardItemGetPayload和filterItems添加到testFilter的依赖数组中,确保函数依赖更新时能生成新的回调版本。
内容的提问来源于stack exchange,提问作者Khant Min Si Thu
相关产品推荐
相关产品推荐

