我在项目中对前端接口请求管理的总结

6,725 阅读5分钟

前言

好久没有更新文章了,刚好最近上手React技术栈和一些新公司项目,有些抽不出时间来,我参与的一些开源项目都停止更新了,文章我也断更很久了,了解我的人都知道,我的文章面向的是一些需要进阶或者正在进阶的一些小伙伴,我的文章虽然不一定有用,但可以给你提供一个方向。一个去思考的方向。

现在社区中大部分的思路都是拿来即用,看过有一些 面试文章 中的内容甚至有出现错误的,一些解析也是半解半惑。通过这次转技术栈( vue & react )我明白了一些软知识带来的习惯,比如 自我思考能力 , 项目拆分能力 , 驱动学习能力 等等。

真正的进阶,在我理解来看就是打破 舒适圈 ,打破壁垒,思考和探索未知,当你慢慢掌握未知,不断寻找壁垒,不断打破壁垒,那么你就是一名合格的工程师了。

为什么写API

我相信在 2020 的今天,大部分前端都是在自己的项目中,将接口作为一个独立的模块划分出来,而在 view 中,只需要进行一个异步的调用就可以捕获到 后台数据 和 异常信息 。

对于将组件单独分离出来的好处就是,我们便于管理,当后台对接口调整的时候,我们只要去对应的模块更改配置信息就好了,而不需要先找页面,在找接口请求方法。

我想应该没有还将请求信息放入在组件中一起写的了吧。QAQ

正文

那么就来说下我对一个 api 的管理吧,纯属个人总结,如果有建议可以在评论区中留言,可以进行讨论和交流。

基本思路

image.png 参考于一个 约定式 的一个形式,对于 api 目录下所有文件名中带有 **.api.js 的文件,我都默认它为一个 API的模块 ,举个例子

- src
-- api
---- user.api.js
---- featrue.api.js
---- index.js

这样的话,就是一个比较良好的一个状态。不论是新入职的开发者,或者是在职开发者,都能够对于 api 有一个规范式的模式在下面。那么最终,只需要将对应模块的 API接口 规范式导出就可以了。

/// @api user.api.js
export default {
    getUserAuth: 'GET /api/user/auth',
    postUser: 'POST /api/user',
    putUser: 'PUT /api/user/:id',
    deleteUser: 'DELETE /api/user/:id',
}

生成函数

最终所有的 API规范式 都会被生成为下面类似的函数

function request () {
	return network({
  	// ...... axios参数
  })
}

如何生产?

在规范式中,导出对象属性的 key 最终会被解析成请求函数的 key ,而值进行切割,最终映射成为 url , method 。至此,一个基本的配置参数就产生出来了,其实这个函数也非常的简单。 generateSyncRequestMethod 方法的主要目的就是将包裹的模块函数化,做一个中间模型

const generateSyncRequestMethod = module => {
  const result = {};
  for (const key in module) {
    const [method, url] = module[key].split(' ')
    result[key] = (options = {}) => {
      console.log('... 函数内部体系')
    }
  }
  return result
}

RESTful规范式

对于 RESTful 来说,依旧是采用约定式的情况来说,必须有一个前后端的交流在内的,这个交流是一个固定的过程,对于接口规范来说,从 A项目  => B项目 来说,这个接口规范来说是一个 Team 的基本规范,做为一个不动式的状态。因此,这个规范式的问题就需要根据团队的形式来进行的,所以这里仅供参考。根据自身团队规范做处理。

使用: GET /api/model/:id ,使用该规范式,那么你在请求方法传入的参数就需要有一定的约束的。首先,在 option 属性中,你需要传入对应在规范接口中声明的 :值 作为一个约束,两者必须相等。

其次,就是对于参数了,中所周知,我们常见的请求方式大致有两个,一个式 data 的形式,常见于 POST  PUT ,而 Get 方法,则是 params ,因此才做了一个规范式,请求参数的属性,由开发者动态灵活的设置,而不是架构来做处理。让其灵活性有一个好的舒适度,同时放开些许灵活性。

request({ id: 1, data: {} })
for (const rest in options) {
  if (url.includes(`:${rest}`)) {
    url = url.replace(new RegExp(`:${rest}`), options[rest]);
    delete options[rest];
    console.log(url, options);
  }
}
return network({
  url,
  method,
  ...options,
});

优点

  • 约定式引导,开发者不必在去进行重复的代码编写
  • 灵活度,对于参数的设置可以和后端进行,在开发时可以进行参数传递,同步到请求配置
  • 同步Mock 对于一些约定式的 Mock 接口,配置相同

缺点

  • 解析接口约定,需要性能消费
  • 生成接口函数,需要有性能消费
  • 函数方法有约束

最终,早生产环境下接口完善后将会独立的打包成为一个 chunk 文件,进行缓存

完整的代码

时间紧迫,TypeScript就没有写了,后续有时间我会补上。

// @api index.js
import network from '@/utils/network'
const PATH = './'
const ISDEEP = false
const REG = /.api.js$/
const MODE = ' sync'
const apiFiles = require.context(PATH, ISDEEP, REG, MODE)

const generateSyncRequestMethod = module => {
  const result = {};
  for (const key in module) {
    const [method, url] = module[key].split(' ')
    result[key] = (options = {}) => {
      for (const rest in options) {
        if (url.includes(`:${ rest }`)) {
          url = url.replace(new RegExp(`:${ rest }`), options[rest])
          delete options[rest]
        } else {
          continue
        }
      }
      return network({
        url,
        method,
        ...options
      })
    }
  }
  return result
}

let apiResult = {}
apiFiles.keys().forEach(element => {
  apiResult = {
    ...generateSyncRequestMethod(apiFiles(element).default)
  }
})

export default apiResult

后话

如果有好的优化方式可以在下面探讨一下,优缺点的话我也进行了一些列举,也在思考一些更加深入的东西,在合理的开销下减少开发者关注api逻辑的关注,而通过约定式对于 api 进行管理。这也是我这个九月份的第一篇文章吧,刚换工作,也在换着技术栈,慢慢的也会输出 React 相关的文章了。

鸽了太久,有一些罪恶感。慢慢的调整状态,明年的目标是6级。最近买了本数据结构的书籍来学习,饿补基础。