如何优雅的控制axios全局错误提醒

看标题可能很多人会觉得又是一篇封装axios的水文, 但请相信这从不是水文, 这种写烂了的axios封装篇多写真没什么意义, 大脸怪的文章全是干货, 坚持看到最后肯定有收获

背景

大脸怪前段时间遇到一个不是 bug 的 bug, 就是一个接口请求报错了, 接口返回了莫名其妙未被处理的错误语, 反正就是只有开发才勉强可以看明白的错误

关键是前端直接拿接口的错误语进行弹窗提醒了, 这可真是太不友好了, 于是产品要求前端隐藏这个错误语

image.png

这其实也没什么, 相信所有的前端都遇到过这个问题, 虽然看起来像是在给后端擦屁股, 但前端解决起来也很简单

真的简单吗?

大脸怪第一时间定位到接口调用的业务代码里, 发现没有写任何错误提醒的代码, 很明显, 错误提醒大概率是写在axios响应拦截器里了, 而且是全局的

经检查, 的确是这样的, 那改起来就有点费事了, 因为涉及到全局的东西, 改动起来就没那么随意了, 一不留神改完一个 bug 多出 n 个 bug

但是凭借大脸怪多年开发经验, 瞬间就想到多个解决方案

方案一: 从业务码着手

由于每个接口都有返回一个业务错误码, 想着能不能通过判断错误码修改错误语, 比如下面这样

假设错误码是 10086

import axios from 'axios'






const request = axios.create()





request.interceptors.response.use(


  (response) => response.data,


  (error) => {


    const code = error?.code
    // 这样写是为了支持判断多个错误码
    if(![10086].includes(code)) {
      // 错误提醒

    }

    return Promise.reject(error)

  }

)



export default request

代码很简单, 但是有个前提, 那就是要保证10086这个业务错误码没有在其他接口用到, 并且以后新增的接口也不能用这个业务码

于是找到后端确认, 后端说当前这个模块确实没有重复用这个业务码, 但不确定其他模块

无可奈何, 为了不给后人制造bug, 只有放弃

方案二: 从接口地址着手

既然业务错误码可能存在重复, 那接口地址总不可能重复吧, 跟方案一其实很像, 直接上代码

假设接口地址是 /aaa/123

import axios from 'axios'






const request = axios.create()





request.interceptors.response.use(


  (response) => response.data,


  (error) => {


    const url = error.config?.url
    // 这样写是为了支持判断多个接口地址
    if(!['/aaa/123'].includes(url)) {
      // 错误提醒

    }

    return Promise.reject(error)

  }

)



export default request

这个思路没什么毛病, 但是当时只是脑子过了一下就直接放弃了, 连代码都没去实现, 为什么呢?

  1. 维护不方便, 每次加一个不需要错误提醒的接口都需要去改一下封装好的axios,这其实是很不好的, 当然也可以把这些不需要错误提醒的接口地址抽出去单独维护
  2. 逻辑控制放在了最后环节, 无法在接口调用的时候就知道是否会错误提醒, 也无法在接口调用的时候控制是否错误提醒

总之, 就是太不优雅了

于是, 大脸怪马上想到了第三种方案

方案三: 在接口调用处控制

鉴于以上两个方案, 要优雅的解决bug, 需要考虑以下几点

  1. 方便维护, 无需频繁修改封装好的axios
  2. 直观, 在接口调用的时候控制是否错误提醒, 也就是做一个类似开关一样的东西

直接上代码

api.js

import request from './request'




export default {
  getList: (params) => request.get('/list', { params, noTip: true }),
  save: (data) => request.post('/save', data, { noTip: true }),
}

request.js

import axios from 'axios'






const request = axios.create()





request.interceptors.response.use(


  (response) => response.data,


  (error) => {


    const noTip = error.config?.noTip
    if(!noTip) {
      // 错误提醒
    }
    return Promise.reject(error)
  }
)

export default request

上面的代码, 其实就是给请求的config添加了一个 noTip 属性, 然后在响应拦截里面判断 config 里的这个值, 只有这个值为 false 时才错误提醒

为什么是反条件 noTip, 而不是正条件 isTip 呢? 用正条件, 当值为 true 时才进行错误提醒, 逻辑不是更清晰吗?

是的, 用正条件确实更清晰一点, 但用正条件的话就得去把之前所有需要全局错误提醒的接口全部加上 isTip: true, 这明显不合理, 而用反条件 noTip 就没有这个困惑, 因为之前需要全局错误提醒的接口这个属性完全可以缺省不传

当然, 如果你的系统刚好是绝大部分接口都是不用全局错误提醒, 只有个别是需要全局错误提醒也可以这样用, 就是很怪, 因为这完全可以取消全局错误提醒, 直接在业务代码里面自行决定提不提醒, 没必要多此一举

以上就是文章的所有内容了, 推荐大家使用方案三, 简单易用好维护, 希望对大家有帮助!


点赞加关注,大脸怪有新思路~

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY8aqbs5' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片