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

为何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不会更新,可能调用旧版本函数引发异常。

解决方案

  1. 添加错误捕获逻辑
    在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] // 补全缺失的依赖
    );
    
  2. 校验API调用参数
    打印getWizardItemGetPayload的返回值,确认type参数符合后端要求;若signal为必填项,需创建AbortController并传入对应signal(同时注意在组件卸载时终止请求,避免内存泄漏)。

  3. 补全useCallback依赖
    将getWizardItemGetPayload和filterItems添加到testFilter的依赖数组中,确保函数依赖更新时能生成新的回调版本。


内容的提问来源于stack exchange,提问作者Khant Min Si Thu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:38:26