目录

🚞 axios 在 Vue 项目中的封装

axios 拥有友好的 API 调用,可以轻松在项目中直接使用。但是随着项目规模越大,如果每发起一次 HTTP 请求,都要进行一遍一遍如 超时时间、请求头、请求地址、错误处理等的重复配置,不仅浪费时间而且让代码变得冗余。

# 封装的内容

在发送请求之前,应该要与后端协商好 请求头、协议、请求地址、请求超时时间的约定。以便对 axios 进行进一步的封装一下内容:

  • 设置接口请求的前缀。 根据开发、测试、生产的三种不同环境,分别配置不同的请求地址前缀。
  • 请求头。例如用户登录状态的验证,在每次发送请求中的请求头中添加 token;或者在请求头中携带一些参数。
  • 状态码。根据接口返回不同的 status ,执行不同的业务。
  • 请求方法。对 getpost 等方法进行再一次封装。
  • 请求拦截器:根据请求的请求头决定,决定哪些请求可以访问。
  • 响应拦截器:根据后端返回的状态码判断执行不同的业务。

# 设置接口的前缀

通常方法。根据 node 环境变量判断区分开发、测试、生产环境。

if (process.env.NODE_ENV === 'development') {
  axios.defaults.baseURL = 'http://dev.xxx.com'
} else if (process.env.NODE_ENV === 'production') {
  axios.defaults.baseURL = 'http://prod.xxx.com'
}
1
2
3
4
5

在本地开发调试时,配置代理服务器 devServer

devServer: {
    proxy: {
      '/proxyApi': {
        target: 'http://dev.xxx.com',
        changeOrigin: true,
        pathRewrite: {
          '/proxyApi': ''
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 设置请求头与超时时间

大部分情况下,请求头都是固定的,只有少部分情况下,会需要一些特殊的请求头。这里设置的是基础的请求头。当需要特殊的请求头时,再将特殊的请求头作为参数传入,覆盖基础配置。

const service = axios.create({
    ...
    timeout: 30000,  // 请求 30s 超时
	  headers: {
        get: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
        },
        post: {
          'Content-Type': 'application/json;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来
        }
  },
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 封装请求方法

// get 请求
export function httpGet({
  url,
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
      params
    }).then((res) => {
      resolve(res.data)
    }).catch(err => {
      reject(err)
    })
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export function httpPost({
  url,
  data = {},
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios({
      url,
      method: 'post',
      transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {
          ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        return ret
      }],
      // 发送的数据
      data,
      // url参数
      params

    }).then(res => {
      resolve(res.data)
    })
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { httpGet, httpPost } from './http'
export const getorglist = (params = {}) => httpGet({ url: 'apps/api/org/list', params })
1
2

# 请求拦截器

这里以在每次请求之前添加 token 为例子。设置如下的拦截器:

axios.interceptors.request.use(
  config => {
    // 每次发送请求之前判断是否存在token
    // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况,此处token一般是用户完成登录后储存到localstorage里的
    token && (config.headers.Authorization = token)
    return config
  },
  error => {
    return Promise.error(error)
  })
1
2
3
4
5
6
7
8
9
10

# 响应拦截器

响应拦截器可以在接收到响应之后先完成一系列的逻辑。

这里以根据状态码判断登录状态、授权,处理错误为例:

// 响应拦截器
axios.interceptors.response.use(response => {
  // 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
  // 否则的话抛出错误
  if (response.status === 200) {
    if (response.data.code === 511) {
      // 未授权调取授权接口
    } else if (response.data.code === 510) {
      // 未登录跳转登录页
    } else {
      return Promise.resolve(response)
    }
  } else {
    return Promise.reject(response)
  }
}, error => {
  // 我们可以在这里对异常状态作统一处理
  if (error.response.status) {
    // 处理请求失败的情况
    // 对不同返回码对相应处理
    return Promise.reject(error.response)
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
📢 上次更新: 2022/09/02, 10:18:16