消除axios响应拦截中冗余if-else的管道模式实现

作者:闭包旅人

时间:2026-10-25

浏览:375

本文介绍一种通过管道模式重构axios响应拦截器的方法,旨在消除繁琐的if-else或switch判断。通过封装一个Enterclose类,利用use方法收集状态码标记与对应回调,配合default处理未匹配情况,最终在拦截器中调用start统一分发。该方案提升了代码可读性与维护性,支持灵活扩展如Promise或finally逻辑,适用于需要集中管理HTTP错误响应的场景。

文章目录

基本拦截

在axios的响应错误拦截逻辑中,开发者通常需要对error.status进行大量的if判断,或者使用switch语句。为了避免这种枯燥且容易出错的编码方式(即给自己挖坑),我们可以尝试采用一种更优雅的拦截器编写姿势。

// 以下大概是日常碰到的操作,拦截响应,判断status做相应操作
function login () {
  console.log('登陆逻辑')
  return promise.reject(error)
}
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response;
}, function (error) {
  if (error.status === 401) {
    // 401重新登录
    console.log('未登陆')
    return login(error)
  } else if (error.status === 404) {
    console.log('404-什么都没')
    return promise.reject(error)
  } else if (error.status === 422) {
    console.log(error.response.data.message)
    return promise.reject(error)
  } else if (error.status === 500) {
    console.log('服务器内部错误')
    return promise.reject(error)
  } else {
    // 其他请求,直接抛出让业务去处理
    return promise.reject(error)
  }
});

设计轮子

思考方向

首先,我们需要明确实现这一功能的核心思路。

  • 核心在于内部消化if的逻辑判断。
  • 根据判断结果执行相应逻辑,这意味着我们需要在内部维护一个逻辑数组(下文称为管道数组),并配合成功后触发对应管道的机制。因此,在开始调用函数执行前,必须先收集好这些管道。该方法需要接收一个标记(用于判断是否匹配)和一个回调函数(匹配成功后执行的逻辑)。
  • 除了传递标记外,还需要传递一个payload(例如拦截器中的error对象)参数。通过payload,我们可以在回调函数中执行更多针对性的操作。
  • 最后,添加一个default函数来收集匹配失败后的处理逻辑。

至此,这个小轮子的核心架构已在脑海中成型。

轮子骨架

// 定义个一个class
class Enterclose {
  constructor () {
    // 维护管道数组
    this.pond = {}
    // 默认管道
    this._default = null
  }
  /**
   * 收集管道
   * callback(payload)
   * @param {any} sign 标记
   * @param {Function|Object} callback 回调函数|函数this
   * @return this
   * */
  use (sign, callback) {
    return this
  }
  /**
   * 收集匹配失败的管道
   * callback(payload)
   * @param {Function} callback 回调函数|函数this
   * @return this
   * */
  default (callback) {
    this._default = callback
    return this
  }
  /**
   * 执行管道流
   * @param {any} sign 标记
   * @param {any} payload
   * @return
   */
  start (sign, payload) {
  }
}

详细实现

上述步骤完成了基本API骨架的编写,接下来将逐步实现内部逻辑。

首先是use方法,用于收集管道。由于需求中标记是唯一的,因此this.ponds的数据结构为{标记: callback}。

use (sign, callback) {
    this.ponds[sign] = callback
    return this
}

其中我们需要一个方法用来启动Enterclose

通过getCallback函数去筛选和标记匹配的管道,返回对应的函数。这样一个消除if的小轮子就搞好啦

start (sign, payload) {
    const fn = this.getCallback(sign)
    if (fn) {
      return fn(payload)
    }
}
/**
* 根据标记获取函数
* @param {*} sign 
* @return {Function}
*/
getCallback (sign) {
    const key = Object.keys(this.ponds).find(key => key === sign)
    if (key) {
      return this.ponds[key]
    } else if (this._default) {
      return this._default
    }
}

实践

创建实例,用use和default收集管道,然后在拦截中通过start触发判断

const enterclose = new Enterclose()
// 收集管道
enterclose
.use(401, function (error) {
  console.log('未登陆')
  return login(error)
})
.use(404, function (error) {
  console.log('404-什么都没')
  return promise.reject(error)
})
.use(429, function (error) {
  console.log(error.response.data.message)
  return promise.reject(error)
})
.use(500, function (error) {
  console.log('服务器内部错误')
  return promise.reject(error)
})
.default(function (error) {
  // 收集默认管道
  return promise.reject(error)
})
axios.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response;
}, function (error) {
  // 启动
  return enterclose.start(error.status, error)
});

你也可以根据自己的场景做一些调整,例如支持Promise啊,或者说加一个finally函数,每次走管道最后都会调用这个回调函数之类

总结

到此这篇关于如何消除axios拦截中if的文章就介绍到这了,更多相关消除axios拦截的if内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章