统一加载整个目录中的 API

统一加载整个目录中的 API

背景:接手的项目已经有一个 api 目录以使用方式如下表示。

src/api:.
│  logs.js
│
├─aiplatform
│      application.js
│      label.js
├─assist
│      assist.js
│
├─base
│      region.js
│
├─classify
│  ├─dialogue
│  │      chat.js
│  │      data.js
│  │
│  ├─label
│  │      index.js
│  │
│  └─mould
│          list.js
│          test.js
│
├─common
│      common.js
│
├─desk
│      notice.js

其中的 js 文件内容示例:

import request from '@/router/axios';

export const getList = (current, size, params) => {
  return request({
    url: '/api/blade-desk/notice/list',
    method: 'get',
    params: {
      ...params,
      current,
      size,
    }
  })
}

export const remove = (ids) => {
  return request({
    url: '/api/blade-desk/notice/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}

所有接口引用方式示例:

import { getList } from "@/api/aiplatform/application";
getList(cnt).then( res => {
  console.log(res.data.data)
})

个人感觉之种方式不太间接,想逐步修改它们。

  • 目录层级划分太多,管理起来十分繁琐
  • 接口声明没有把 method 和 url 以及参数进行封装,声明一个接口得首先一陀代码
  • 每个使用时都必须 import { xxxx } "..."
  • 接口响应中的主要数据部分没有经过统一处理,每个使用的地方都得 res.data.data...

修改后的调用方式

  • 直接引用,无需导入
  • 直接返回响应中的主要数据
this.$api.aiplatform.application.getList(cnt).then( res => {
  console.log(res) //
})

实现方式

在 api 目录下创建 index.js 文件,内容为:

import lodash from 'lodash'
const files = require.context('./', true, /.js$/);
const apiMaps = {}
files.keys().forEach(key => {
  const path = key.replace(/^./|.js$/g, ``).replace(///g, `.`)
  const obj = files(key) // 如果文件内容写了 export default, 那么这里是 files(key).default
  const objRes = {}
  Object.keys(obj).forEach(key => { // 对每个 API 统一添加拦截器, 本来这个功能应该在 axios 的, 为了不影响已有的代码,另开了一个功能
    let fn = obj[key]
    objRes[key] = (...arg) => {
      return new Promise((resove, reject) => {
        fn(...arg).then(res => {
          const inRes = (res) => { // 响应拦截器
            if(res.status === 200) {
              return res.data.data
            } else {
              throw new Error(res.msg)
            }
          }
          resove(inRes(res))
        }).catch(err => {
          reject(err)
        })
      })
    }
  })
  lodash.set(apiMaps, path, objRes)
})
export default apiMaps

在入口 main.js 中添加以下内容:

import api from '@/api'
Vue.prototype.$api = api

然后就能在使用的地方通过 this.$api.目录.方法 的形式调用接口了,不影响原来的调用方式。

核心知识点

  • webpack 中的 require.context
原文地址:https://www.cnblogs.com/daysme/p/14511076.html