try...catch 未捕获到 Promise 异常的问题

1,问题表现

一般在前端项目开发中,请求会统一处理:增加请求拦截器和响应拦截器。在响应拦截器中,可能会有如下逻辑:

axios 为例:

// 响应拦截器
axios.interceptors.response.use(
  (response) => {
    if (response.data.code === "000000") {
      return Promise.resolve(response);
    } else {
      // 非 000000 也算错误
      return Promise.reject(response);
    }
  },
  // 状态码非 200
  (error) => {
    return Promise.reject(error);
  }
);

在业务代码中,同事问我为啥没有跳转?下面是我模拟的代码逻辑:

const getInfo = () => {
  // 模拟状态码 200,但 code !== 100013 的情况
  return Promise.reject({ code: "100013", msg: "出错了" });
};

const handleClick = async () => {
  try {
    getInfo().then((data) => {
      // 其他逻辑
      console.log('data', data);
    });
  } catch (error) {
    if (error.data.code === '100013') {
      // 跳转逻辑
      console.log('error', error);
    }
  }
};

handleClick();

2,原因分析

getInfo() 返回的是一个 rejected 状态的 Promise 对象,注意它是一个对象,并没有报错或是异常,所以不会走到 try...catch 中的 catch 中。另外:

  • then() 处理函数,但 then() 不会执行;
  • 没有 catch() 处理函数,所以获取不到 rejected 已决状态的结果。

3,解决

更改如下即可:

const handleClick = () => {
  try {
    getInfo()
      .then((data) => {
        // 其他逻辑
        console.log("data", data);
      })
      .catch((error) => {
        if (error.data.code === "100013") {
          // 跳转
          console.log("error", error);
        }
      });
  } catch (error) {
    // 其他执行错误
  }
};

或使用 await

await 用于等待一个 Promise 对象已决后,获取已决后的结果,如果结果为 rejected 状态,则抛出异常,可以用 try...catch 捕获。Promise 参考

const handleClick = async () => {
  try {
    const data = await getInfo();
    // 其他逻辑
    console.log("data", data);
  } catch (error) {
    if (error.data.code === "100013") {
      // 跳转
      console.log("error", error);
    }
  }
};

3,其他相关

从 finally 语句块返回 会是什么情况?

如果从 finally 块中返回一个值,那么这个值将会成为整个 try-catch-finally 的返回值,无论是否有 return 语句在 trycatch 中。这包括在 catch 块里抛出的异常。

注意下面的2段代码的执行结果:

(() => {
  try {
    try {
      throw new Error("oops");
    } catch (ex) {
      console.error("inner", ex.message);
      throw ex;
    } finally {
      console.log("finally");
    }
  } catch (ex) {
    console.error("outer", ex.message);
  }
})();

// inner oops
// finally
// outer oops

下面代码只是多了一个return

(() => {
  try {
    try {
      throw new Error("oops");
    } catch (ex) {
      console.error("inner", ex.message);
      throw ex;
    } finally {
      console.log("finally");
      return;
    }
  } catch (ex) {
    console.error("outer", ex.message);
  }
})();

// inner oops
// finally

以上。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值