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

Axios登录请求异常:成功时仍触发catch块求助

问题排查与解决方案

嘿,咱们来拆解下你遇到的这个“then和catch同时执行”的问题——核心原因其实有两个,咱们一步步理清楚:

问题根源

  1. async/await 与 .then/.catch 混合使用导致错误处理混乱
    你在handleLogin这个async函数里同时混用了await和.then/.catch链式调用。async函数本身会返回一个Promise,一旦.then回调内部抛出未捕获的错误,这个错误会直接冒泡到外层的.catch块,就会出现你看到的“两边逻辑都执行”的诡异情况。

  2. .then回调里存在未捕获的运行时错误
    重点看你.then里的this.InEmail.focus()——这里的this指向大概率出问题了!因为你用的是箭头函数作为.then的回调,箭头函数的this继承自定义它时的外层上下文,而不是组件实例。当你调用this.InEmail时,大概率拿到的是undefined,再调用focus()就会抛出错误,这个错误没被处理,直接触发了外层的.catch块。


修复方案:统一用 async/await + try/catch(推荐)

把混合写法改成纯async/await风格,错误处理更清晰,同时修正this指向的问题(如果是React Native项目,建议用useRef获取输入框引用)。

修改后的代码示例:

// 先在组件里定义输入框的ref(假设是函数组件)
const emailRef = useRef(null);

async function handleLogin() {
  try {
    // 清除旧的登录存储
    await AsyncStorage.removeItem('Authorization');
    await AsyncStorage.removeItem('ImAuthenticated');

    // 发起登录请求
    const response = await api.post('/login', { email, password }, {
      headers: { 'device': 'mobile' }
    });

    const { hash } = response.data;
    // 存储登录状态(注意:AsyncStorage只能存字符串)
    await AsyncStorage.setItem("Authorization", hash);
    await AsyncStorage.setItem("ImAuthenticated", "true");

    // 跳转到菜单页
    navigation.navigate('Menu');
    console.log('oi');
  } catch (error) {
    // 统一处理所有错误:包括请求失败、代码运行时错误
    if (error.response?.data?.showIn === "text") {
      setShowInfo(true);
      setEmail('');
      setPass('');
      emailRef.current?.focus(); // 用ref安全获取输入框并聚焦
      setColorInfo(error.response.data.level !== 3);
      setInfoText(error.response.data.error);
    } else {
      setshowBox(true);
      setEmail('');
      setPass('');
      emailRef.current?.focus();
      setcolorBox(error.response.data.level !== 3);
      setboxText(error.response.data.error);
    }
  }
}

关键修复点

  • 移除混合写法:用try/catch统一处理所有错误,包括请求失败和代码运行时错误,避免错误冒泡混乱。
  • 修正AsyncStorage存储类型:AsyncStorage只能存储字符串,你之前存布尔值true会被自动转成字符串,但显式写"true"更稳妥。
  • 修复输入框聚焦的this问题:用useRef获取输入框实例,替代this.InEmail,彻底解决this指向错误。
  • 添加可选链操作符:error.response?.data避免了当error没有response属性时抛出新的错误,让错误处理更健壮。

如果你坚持要用.then/.catch写法

那需要在.then的回调内部也加一个try/catch,捕获回调里的运行时错误:

// 同样先定义ref
const emailRef = useRef(null);

async function handleLogin(){
  await AsyncStorage.removeItem('Authorization');
  await AsyncStorage.removeItem('ImAuthenticated');
  await api.post('/login', { email, password }, { headers: { 'device': 'mobile' } })
  .then(async(response)=>{
    try {
      const { hash } = response.data;
      await AsyncStorage.setItem("Authorization", hash);
      await AsyncStorage.setItem("ImAuthenticated", "true");
      navigation.navigate('Menu');
      console.log('oi');
    } catch (innerError) {
      // 处理.then回调内部的错误,比如AsyncStorage或navigation的错误
      console.error('Then回调内部错误:', innerError);
    }
  }).catch(function (error){
    // 原来的错误处理逻辑
    if(error.response.data.showIn == "text"){
      setShowInfo(true);
      setEmail('');
      setPass('');
      emailRef.current?.focus();
      setColorInfo(error.response.data.level !== 3);
      setInfoText(error.response.data.error);
    }else{
      setshowBox(true);
      setEmail('');
      setPass('');
      emailRef.current?.focus();
      setcolorBox(error.response.data.level !== 3);
      setboxText(error.response.data.error);
    }
  });
}

不过还是更推荐第一种纯async/await + try/catch的写法,代码可读性和维护性更强,错误处理逻辑也更直观。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:54:02