写一个不一样的API封装

131 阅读2分钟

前后端交互是最基础的功能,本文所说是我在最近一个项目中对API和请求的封装,这些对每个项目来说都是必须的,下面分享我的一些简化方法。 首先是对API的封装,先来看目录结构:

image.png

在modules目录中存放的是各个模块的api,axios.js是对全局请求的封装,apiList.js中主要用于动态导入一组模块,并将它们作为对象的属性存储在 API 对象中,这是为了相关的模块统一管理,统一使用。

// apiList.js
const req = import.meta.globEager('./modules/*.js')

const api = {}
for (const key in req) {
  const name = key.replace(/^\.\/modules\/(.*)\.\w+$/, '$1')
  const value = req[key]
  api[name] = value.default
}
const API = api

export default API
  1. 首先,使用vite的import.meta.globEager方法来动态导入以 .js 结尾的所有模块文件。这会返回一个对象,其中键是模块路径,值是模块的内容。
  2. 第二步,遍历导入的模块对象中的键,name中使用正则表达式将模块路径转换为模块的名称(即去除路径和文件扩展名),value则是获取模块的内容。
  3. 第三步,api[name] = value.default,是将模块的默认导出赋值给 api 对象的属性,属性名为模块的名称,再将 API 对象作为默认导出。

在modules目录下,我们可以把模块命名为一个变量,再默认导出,如:

// user.js
import http from '../axios'

const admin = {
  getInfo(data) {
    return http({
      url: '/login/getUserInfo',
      method: 'get',
      params: data
    })
  }
}
export default admin

然后在main.js中引入挂载到全局:app.config.globalProperties.$API = API

在组件中只需要通过getCurrentInstance()函数获取实例,然后引用即可,例:

const API = getCurrentInstance().proxy.$API
API.user.getInfo(data)

在就是对请求的封装

import axios from 'axios'
import {
  getToken,
    ...
} from '@/core/auth.js'
import baseURL from './url'
import Router from '../router'
import { ElMessage } from 'element-plus'

// 创建实例
const http = axios.create({
  baseURL,
  timeout: 15000
})
// 设置post请求头
http.defaults.headers.put['Content-Type'] = 'application/x-www-form-urlencoded'
// http.defaults.withCredentials = true //是否携带密钥信息
// 请求拦截 -->在请求发送之前做一些事情
http.interceptors.request.use(
  config => {
    config.headers.Authorization = getToken() || ''
    ...
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截 -->在返回结果之前做一些事情
http.interceptors.response.use(
  response => {
    const data = response.data
    // 其他
    if (data.status === 200 || data.success) {
      return data.data || data.object
    } else if (data.resCode === '10000') {
      // 登录过期
      Router.replace({ path: '/loginIndex' })
      removeInfo()
      return Promise.reject(response.data)
    } else {
      ElMessage({
        message: data.message || data.msg,
        type: 'error',
        duration: 2000
      })
      return Promise.reject(response.data)
    }
  },
  error => {
    const data = error.response
    if (data && data.status === 403) {
      return Promise.reject(error)
    }
    if (data && data.status === 500) {
      ElMessage({
        message: '服务器出小差了,稍后重试~',
        type: 'error',
        duration: 2000
      })
    }
    return Promise.reject(error)
  }
)
export default http

这是一些常见的对请求的封装,对一些错误请求也都做了处理。

当然有些特殊的需求,比如取消请求可以创建一个取消请求CancelToken实例,当然我在这个项目中没有用到