当前位置:   article > 正文

axios的封装_axios封装

axios封装

在vue项目中我们一般会使用axios来实现前后端的交互,下面是常用的axios封装,包括了请求头、状态码、请求超时时间、请求方式、请求拦截器和响应拦截器等的封装:

首先需要先安装axios,使用如下命令:

  1. npm install axios

我们一般会在src目录下新建一个文件夹api,然后在此文件夹下创建一个request.js文件,对axios的封装代码就写在request.js文件中,目录结果见下图

主要内容拆解:

1.请求超时时间设置,可根据实际项目需求而定

  1. const request = axios.create({
  2. baseURL: '',
  3. timeout: 60000, //改成60s
  4. })

 2.添加请求拦截器--(由于项目中有使用到上传和导入功能,参数与一般请求有区别,这里做了分类处理,如果不需要对参数做处理的,可以去掉type==='upload'的判断部分代码)

  1. request.interceptors.request.use(
  2. (config) => {
  3. config.data = config.data || ''
  4. const { data, type, basic } = config.data
  5. if ( process.env.NODE_ENV === 'development' ) {
  6. config.url = `${config.baseUrl || '/api'}${config.url}`
  7. } else {
  8. config.url = `${config.url}`
  9. }
  10. if (data && basic) return config //如果传参时有传 basic 则不需要再加一次basic
  11. if (config.url !== '/login') { // 判断请求是否是登录接口
  12. config.headers.token = localStorage.getItem('token') // 如果不是登录接口,就给请求头里面设置token
  13. }
  14. config.data = type === 'upload' ? data : formatParams(config.data)
  15. return config // 返回这个配置对象,如果没有返回,这个请求就不会发送出去
  16. },
  17. (error) => {
  18. return Promise.reject(error)
  19. }
  20. )

其中basic中包括token、ver(版本号)、time(时间戳)等公共的接口参数,一般我们会在src下的utils文件夹中创建一个basic.js的文件,代码如下:

  1. import MD5 from 'js-md5'
  2. import SHA512 from './secret/sha512' // sha512加密
  3. import { getToken } from '@/utils/auth.js'
  4. /**
  5. * 生成32位随机正整数 0~2147483647 (2^32)
  6. */
  7. export const getNonce = () => Math.floor(Math.random() * 2147483646 + 1)
  8. /**
  9. * 生成basic数据
  10. * @param ver {string} 必填 -- 版本号
  11. * @param time {number} 必填 -- 时间戳
  12. * @param id {string} 必填 -- 0
  13. * @param nonce {string} 必填 -- 32位随机数
  14. * @param token {string} 非必填 -- 登陆成功后必填,从后台获取,在localStorage中存取
  15. * @param sign {string} 非必填 -- 签名,从后台获取,在localStorage中存取
  16. */
  17. export const getBasic = ({
  18. ver = '1.0',
  19. time = new Date().getTime(),
  20. id = 1,
  21. nonce = getNonce(),
  22. token = getToken(),
  23. sign
  24. } = {}) => {
  25. return { ver, time, id, nonce, token, sign }
  26. }
  27. /**
  28. * 生成sign签名
  29. * @param {Object} obj: 必须有pwd属性
  30. * @param {array} argsArray 拼接项数组
  31. */
  32. export const creatSignForDpikey = (obj, argsArray) => {
  33. let str = ''
  34. let arr = argsArray
  35. if (!arr) {
  36. arr = Object.keys(obj).filter(v => v !== 'pwd')
  37. }
  38. arr.sort()
  39. for (let key of arr) {
  40. str += obj[key]
  41. str += '#'
  42. }
  43. str += MD5(obj['pwd'])
  44. let Mstr = SHA512.encrypt(str)
  45. return Mstr
  46. }

2.添加响应拦截器--响应拦截器中包含对错误码的处理,此处我们一般会新建errorCode.js文件,将需要统一在页面上弹出提示的错误码写在此文件中(好处就是不需要在代码里面每个接口返回的错误码都写一次提示处理,只需要针对需要特别处理的个别错误码做处理例如提示后还有下一步操作的情况就需要特殊处理)

  1. request.interceptors.response.use(
  2. (res) => {
  3. let langType = getLocale() || 'en-US'
  4. if (res.status != 200) {
  5. return false
  6. }
  7. let code
  8. if (res.data.basic) {
  9. code = res.data.basic.code // 获取后端返回的状态码
  10. if (code === 200) { //接口状态码
  11. return res.data
  12. } else if (code === 20004 || code === 10002 || code === 7009 || code === 7088 || code === 7090 || code === 7004 ) { // Invalid token Token expires // Token达到最大数量后被强制退出
  13. if (showLoginMsg) { // token过期导致请求失败,返回登录页后只弹出一个异常提示
  14. Message.error(errorCode[langType][code])
  15. logout()
  16. showLoginMsg = false
  17. setTimeout(() => {
  18. showLoginMsg = true
  19. }, 3000)
  20. }
  21. return Promise.reject(code)
  22. }
  23. else { //例如公共的 其他code 默认3秒 改为2秒
  24. Message.error(errorCode[langType][code]) //改为这种写法后 即使没有翻译 codeMsg也不为false
  25. if (codeMsg && (codeMsg !== `errorCode[langType][code]`)) {
  26. if (showOtherMsg) {
  27. Message({ message: codeMsg,duration: 2000,type: 'error' })
  28. showOtherMsg = false
  29. setTimeout(() => {
  30. showOtherMsg = true
  31. }, 2000)
  32. }
  33. } else if (!specialCode.includes(code)) {
  34. if (showOtherMsg) {
  35. Message({ message: res.data.basic.msg,duration: 2000,type: 'error' })
  36. showOtherMsg = false
  37. setTimeout(() => {
  38. showOtherMsg = true
  39. }, 2000)
  40. }
  41. }
  42. return Promise.reject(res.data)
  43. }
  44. } else {
  45. return res.data
  46. }
  47. },
  48. (error) => {
  49. // axios判断请求超时进行处理
  50. let langType = getLocale() || 'en-US'
  51. if (error.message.includes('timeout')) {
  52. if (showOtherMsg) {
  53. Message({
  54. message:message: errorCode[langType]['12345'],
  55. type: 'error',
  56. duration: 2 * 1000,
  57. })
  58. showOtherMsg = false
  59. setTimeout(() => {
  60. showOtherMsg = true
  61. }, 2000)
  62. }
  63. } else if (error && error.response) {
  64. // 处理失败的状态码 状态码404 500 503之类的
  65. let statusCode = error.response.status
  66. if (showOtherMsg) {
  67. Message({ message: errorCode[langType][statusCode],duration: 2000,type: 'error' })
  68. showOtherMsg = false
  69. setTimeout(() => {
  70. showOtherMsg = true
  71. }, 2000)
  72. }
  73. } else if (error.message == 'Network Error') {
  74. if (showOtherMsg) {
  75. Message({
  76. message:errorCode[langType]['12344'],
  77. type: 'error',
  78. duration: 2 * 1000,
  79. })
  80. showOtherMsg = false
  81. setTimeout(() => {
  82. showOtherMsg = true
  83. }, 2000)
  84. }
  85. }
  86. return Promise.reject(error)
  87. }
  88. )

request.js中的完整的代码如下:

  1. /* eslint-disable no-undef */
  2. import axios from 'axios'
  3. import Vue from 'vue'
  4. import router from '../router' // 获取路由
  5. import { Message } from 'element-ui' // message提示信息组件
  6. import { getBasic } from '@/utils/basic'
  7. import { errorCode } from '@/utils/errorCode'
  8. import { specialCode } from '@/utils/specialCode'
  9. import { getLocale } from '@/lang'
  10. import store from '@/store'
  11. import { logout } from '@/utils/common'
  12. // 生产地址
  13. // axios.defaults.baseURL = serverBase; // 配置axios请求的地址
  14. const request = axios.create({
  15. baseURL: '',
  16. timeout: 60000, //改成60s
  17. })
  18. // 格式化请求参数
  19. const formatParams = (params) => {
  20. const basic = getBasic()
  21. return {
  22. basic,
  23. data: params
  24. }
  25. }
  26. let showLoginMsg = true
  27. let showOtherMsg = true
  28. // 请求拦截器
  29. request.interceptors.request.use(
  30. (config) => {
  31. config.data = config.data || ''
  32. const { data, type, basic } = config.data
  33. if ( process.env.NODE_ENV === 'development' ) {
  34. config.url = `${config.baseUrl || '/api'}${config.url}`
  35. } else {
  36. config.url = `${config.url}`
  37. }
  38. if (data && basic) return config //如果传参时有传 basic 则不需要再加一次basic
  39. if (config.url !== '/login') { // 判断请求是否是登录接口
  40. config.headers.token = localStorage.getItem('token') // 如果不是登录接口,就给请求头里面设置token
  41. }
  42. config.data = type === 'upload' ? data : formatParams(config.data)
  43. return config // 返回这个配置对象,如果没有返回,这个请求就不会发送出去
  44. },
  45. (error) => {
  46. return Promise.reject(error)
  47. }
  48. )
  49. // 响应拦截器
  50. request.interceptors.response.use(
  51. (res) => {
  52. let langType = getLocale() || 'en-US'
  53. if (res.status != 200) {
  54. return false
  55. }
  56. let code
  57. if (res.data.basic) {
  58. code = res.data.basic.code // 获取后端返回的状态码
  59. if (code === 200) { //接口状态码
  60. return res.data
  61. } else if (code === 20004 || code === 10002 || code === 7009 || code === 7088 || code === 7090 || code === 7004 ) { // Invalid token Token expires // Token达到最大数量后被强制退出
  62. if (showLoginMsg) { // token过期导致请求失败,返回登录页后只弹出一个异常提示
  63. Message.error(errorCode[langType][code] )
  64. logout()
  65. showLoginMsg = false
  66. setTimeout(() => {
  67. showLoginMsg = true
  68. }, 3000)
  69. }
  70. return Promise.reject(code)
  71. }
  72. else { //例如公共的 其他code 默认3秒 改为2秒
  73. const codeMsg = errorCode[langType][code] //改为这种写法后 即使没有翻译 codeMsg也不为false
  74. if (codeMsg && (codeMsg !== `errorCode[langType][code] `)) {
  75. if (showOtherMsg) {
  76. Message({ message: codeMsg,duration: 2000,type: 'error' })
  77. showOtherMsg = false
  78. setTimeout(() => {
  79. showOtherMsg = true
  80. }, 2000)
  81. }
  82. } else if (!specialCode.includes(code)) {
  83. if (showOtherMsg) {
  84. Message({ message: res.data.basic.msg,duration: 2000,type: 'error' })
  85. showOtherMsg = false
  86. setTimeout(() => {
  87. showOtherMsg = true
  88. }, 2000)
  89. }
  90. }
  91. return Promise.reject(res.data)
  92. }
  93. } else {
  94. return res.data
  95. }
  96. },
  97. (error) => {
  98. // axios判断请求超时进行处理
  99. let langType = getLocale() || 'en-US'
  100. if (error.message.includes('timeout')) {
  101. if (showOtherMsg) {
  102. Message({
  103. message: errorCode[langType]['12345'],
  104. type: 'error',
  105. duration: 2 * 1000,
  106. })
  107. showOtherMsg = false
  108. setTimeout(() => {
  109. showOtherMsg = true
  110. }, 2000)
  111. }
  112. } else if (error && error.response) {
  113. // 处理失败的状态码 状态码404 500 503之类的
  114. let statusCode = error.response.status
  115. if (showOtherMsg) {
  116. Message({ message:errorCode[langType][statusCode],duration: 2000,type: 'error' })
  117. showOtherMsg = false
  118. setTimeout(() => {
  119. showOtherMsg = true
  120. }, 2000)
  121. }
  122. } else if (error.message == 'Network Error') {
  123. if (showOtherMsg) {
  124. Message({
  125. message: errorCode[langType]['12344'],
  126. type: 'error',
  127. duration: 2 * 1000,
  128. })
  129. showOtherMsg = false
  130. setTimeout(() => {
  131. showOtherMsg = true
  132. }, 2000)
  133. }
  134. }
  135. return Promise.reject(error)
  136. }
  137. )
  138. export default request

在项目中使用示例:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/446246
推荐阅读
相关标签
  

闽ICP备14008679号