lc-universe-ajax v0.0.2
@lx-frontend/ajax
一个规范Ajax使用的框架
安装
使用npm:
npm install @lx-frontend/ajax
使用yarn:
yarn add @lx-frontend/ajax
Example
// 请求库实例
import axios from 'axios';
import { Ajax } from '@lx-frontend/ajax';
// rest配置
const rest = {
firstModule: {
getCall: ['get', '/the/request/url', requestOptions],
postCall: ['post', '/the/post/url', requestOptions]
}
}
// 实例化配置
const options = {
rest,
baseUrl
}
// 实例化
const ajax = new Ajax(options)
完成Ajax实例化之后,即可使用如下方式发起请求:
ajax.$rest.firstModule.getCall().then(res => {/***/})
ajax.$rest.firstModule.postCall(data).then(res => {/***/})
options配置
// const ajax = new Ajax(options)
{
rest
baseUrl
// boolean,是否发送FormData类型的数据,如果为true,则会将data数据转化成FormData形式,且修改请求头header中的Content-Type字段,默认为false,发送json数据
sendFormData
// wx/node/browser 如果是node或browser可以省略该参数
// 如果是wx,则必须带上该参数,且需要将wx对象传递给engine
envType,
// 发起请求的引擎,node和browser不需要该参数
// 微信环境则需要将微信引擎对象传递给该属性,配合envType使用
engine,
// ... 其他axios支持的所有配置
}
rest
该框架要求所有请求必须属于一个模块,rest对象的每个属性则代表一个模块,模块下是具体的请求函数配置。
rest的配置遵循如下模式:
{
moduleName: {
funcName: [method, url, requestOptions]
// ...
}
// ...
}
例如:
如下rest配置中,firstModule
是模块名称,该模块下有两个名为getCall
和postCall
的请求
const rest = {
firstModule: {
getCall: ['get', '/the/request/url', {/* requestOptions */}],
postCall: ['post', '/the/post/url', {/* requestOptions */}]
}
}
rest的结构决定了Ajax在实例化之后的调用方式,比如,getCall
和postCall
将通过如下方式调用:
// const ajax = new Ajax(options)
// 实例化之后,请求函数组成的模块将被挂载到 $rest 属性下
ajax.$rest.firstModule.getCall().then(/***/)
ajax.$rest.firstModule.postCall().then(/***/)
请求配置 method, url, requestOptions
模块下具体的请求通过一个三元数组配置而来,数组项分别表示:请求的方法,请求的路径,以及对请求的配置。
method: string类型,目前仅支持get, put, post, patch, delete方法
url: string类型,该路径将和requestOptions的baseUrl属性拼接,组成最终的请求路径。
requestOptions: object, 详见requestOptions
requestOptions
requestOptions的参数有两种类型
- 初始化参数中,除rest,engineType,engine之外的参数,如果和初始化参数重复,则这里的优先级最高
- 任何自定义的参数,该参数会被携带在请求响应response中,可以通过该参数在拦截器中执行任何逻辑
{
baseUrl,
sendFormData,
// ...
}
ajax实例方法
// 实例化
const ajax = new Ajax(options)
ajax.extend(obj) // 直接将obj上的属性赋值到ajax对象上
ajax.extendRest(mod) // 扩展$rest对象,mod的配置格式见rest对象下的属性
在Vue中使用
import { Ajax } from '@lx-frontend/ajax'
const ajax = new Ajax(options)
Vue.use(Ajax)
const app = new Vue({
ajax,
// ...
})
插件的作用是,声明了一个全局的mixin,在应用始化阶段,获取ajax.$rest,并将将其挂载到Vue.prototype上,方便在页面组件中以this.$rest的方式获取ajax上的请求方法。
对项目遗留配置的兼容
改造旧项目时,原项目ajax配置的query
, create
, delete
, putWay
, patchWay
方法在该库中并不存在,一一去修改这些配置工作量太大,所以下面提供了一种兼容的方法:
import { Ajax, compatibleMethods } from '@lx-frontend/ajax'
import { Ajax } from '@lx-frontend/ajax'
const ajax = new Ajax(options)
// compatibleMethods方法则为ajax添加了`query`, `create`, `deletes`, `putWay`, `patchWay`方法
compatibleMethods(ajax)
需要注意的一点是,delete是JS的保留关键字,无法通过代码添加delete方法,所以将delete
改为了deletes
。
所以原配置只需要做很小的修改,即,将ajax.delete
改为ajax.deletes
,即可正常工作。
对于新项目则可以不引入该函数,打包时利用treeshaking将该函数代码去除即可。
如何完善项目的ajax的typescript校验?
鉴于目前大部分项目都有restConfig和调用ajax.extendRest,下面将以此为例子。
- 首先是 ajax.extendRest 和 new Ajax() 需要进行分离。 如果不将两者分离,就不太方便处理模块化调用后的restConfig类型。
- 分离后调用项目内的 IRestTypes 组织类型。一般情况下都可以满足,如果不满足可以来补充或者群里喊一下。
- 给实例挂上$rest的类型。
// /ajax/instance.js
import Ajax, { compatibleMethods } from '@lx-frontend/ajax'
import { interceptRequest, interceptSuccess, interceptFail } from './interceptor'
const ajax = new Ajax({})
compatibleMethods(ajax)
ajax.interceptors.request.use(interceptRequest)
ajax.interceptors.response.use(interceptSuccess, interceptFail)
export default ajax
// /ajax/index.ts
import ajax from './instance'
import { IRestTypes } from '@lx-frontend/ajax'
import rest from '../rest/config'
export type IRest = IRestTypes<typeof rest>
type IAjax = {
$rest: IRest
}
export default ajax as IAjax
- 给全局挂上$rest的类型
import { IRest } from '@/ajax'
// *.d.ts
declare module 'vue/types/vue' {
// Vue 的全局属性
interface Vue {
$rest: IRest
navigateTo: Function
navigateBack: Function
$route: any,
showWarningMessage: Function
setEvaluateParams: Function
showErrorMessage: Function
redirectTo: Function
$eventCenter: any
}
}
- 如何改写typescript自动推导的类型?
import { ReWrite, PromiseResponse } from '@lx-frontend/ajax'
import rest from '../rest/config'
interface User {
showPopup: (params: IShowPopupReq) => PromiseResponse<IShowPopupRes>
}
export type IUser = ReWrite<typeof rest.user, User>
export type IRest = IRestTypes<typeof rest>
export interface IRestConfig extends IRest {
user: IUser
}