![c55935234e0bcd0f1932ce2dfaef2873.png](https://i-blog.csdnimg.cn/blog_migrate/e46f1d6330f0a7fc8730e483bc5b9ea3.jpeg)
请求层框架是什么?
其实 axios 就可以看成一个请求层框架,只不过它将关注焦点放在了 ajax request 上,更多时候大家把它当成一个库。
那么这里的”框架“指的是什么呢?一般来说,实际项目中发ajax请求,不仅仅是发出去这么简单,一方面数据需要 transform、polyfill 等一系列操作,另一方面请求发出去的过程中可能需要触发一些副作用,比如打点统计等等,最后,在跨端场景下,最终把请求发出去的backend,可能有多种。比如在electron项目中,假设我们使用UDP协议发送请求,但是为了支持外网向内网推数据,又没有打洞服务的情况,我们需要在某个版本中支持外网 TCP server -> 内网 TCP client 的模式。
通过一个图,大家就可以理解为什么请求层值得被称为一个框架:
![0c952a313b1063b2dc8da0e56f686192.png](https://i-blog.csdnimg.cn/blog_migrate/be8a808dc311504065270010395a03fb.jpeg)
这么一看功能还不少对吧?而且是典型的中间件模式(绿色的全是中间件),说是框架不过分吧?
如何实现一个请求层框架?
实现这样一个框架,我们主要要解决两个问题:
- 设计一个中间件架构的请求层runtime。
- 定义接口声明的流程和语法。
请求层runtime
为什么说 axios 本身就可以看成一个请求层框架呢?因为它支持 transformRequest 和 transformResponse,这个其实就是中间件接口,当然你也可以理解为hook,总而言之,你可以把各种中间环节通过这俩接口塞到 axios 里面去。
为了实现更丰富的功能以及更高水平的自定义,我们可以部分基于 axios,自己实现一套请求层,接口定义类似下面这样:
import
接口声明
看到上面的代码,你一定不会去使用这个框架,因为语法太蛋疼了。
这里的关键问题是,”接口声明“从哪里来?
要么生成,要么手写。
生成接口声明,需要后端支持,比如 swagger 就有这个功能,它要求后端在编写接口之前,先编写接口声明,swagger 会根据声明生成各种前端代码。这样做的优势在于,接口声明处于中立位置,与具体的技术方案没有关系,方便我们未来对接口声明做各种处理,深度使用。劣势在于,它相当于重塑了开发流程,有可能产生现实阻力。
手写接口声明,核心问题是如何让语法优雅而简练,真正达到声明,而不是编程的体验。
目前业界有没有完整的开源接口声明方案(经评论提醒,pont是一个很好的方案),我还没有调研清楚,但是针对单个功能点,尤其是和出参入参有关的(其实主要就是validator),其实有很多工具可以用,比如:
joiwww.npmjs.com![a6ddc4f503cbae17045235facbc53e8f.png](https://i-blog.csdnimg.cn/blog_migrate/35193a708b8ce897d3dabc8db18cc5f1.jpeg)
![a6ddc4f503cbae17045235facbc53e8f.png](https://i-blog.csdnimg.cn/blog_migrate/35193a708b8ce897d3dabc8db18cc5f1.jpeg)
![a6ddc4f503cbae17045235facbc53e8f.png](https://i-blog.csdnimg.cn/blog_migrate/35193a708b8ce897d3dabc8db18cc5f1.jpeg)
这些工具都能帮助你实现接口声明,但是使用它们的体验,仍然是编程体验。我们希望事情变得更简单,于是,typescript该出场了。
typescript 运行时应用
解释一下什么是”运行时“应用——ts原本是在构建期起作用的,在代码编译过程中,type declare信息会被擦除掉,最终生成js代码。而”运行时“应用,就是说我们希望通过某种方式,把类型信息带入运行时,让它发挥一些作用,而本篇文章介绍的请求层框架,就是我们的一种尝试。
其实这个框架的runtime,原本就存在,但是就像我上面所说的,接口语法不够友好,以至于大家根本不想用。然后我有个同事,很厉害,他自己在项目里面实现了一个自定义的webpack-loader,能把ts声明的接口,转换成请求层调用代码。
他的loader和原本的runtime一结合,就是一个完整的请求层框架了。
它的接口声明语法是类似这样的:
type
你只要声明接口和参数类型,整个请求层的管道连接,以及数据校验的实现代码,loader都可以给你生成。如果自动生成的validator不和你的要求,你还可以自己编写,loader会根据类型声明,自动查找你的validator。
有这么个神器在,框架的实用性产生了质的飞跃。因为接口声明是ts,所以我们在VSCode里面调用接口的时候,有比较完善的智能提醒,这一点比使用json等静态格式声明接口,要舒服的多。
其实框架本身,并不重要,写这篇文章,主要是想跟大家展示一下ts类型信息在运行时发挥作用的潜力。我19年给自己立的一个目标,就是探索出一套系统方法,把ts类型信息带到业务中去,让其发挥作用。
然而在这个领域,我已经落后了,写自定义loader的同事,真是干得漂亮。