@ysfe/request
v1.4.10
Published
宇石前端 - 基于 axios 的 Http 请求库扩展
Downloads
2
Readme
@ysfe/request
Introduction
描述
基于 axios 的 二次封装, 提供插件化的通用能力.
特性扩展
- 请求防抖
- 最大请求并发限制
- url 格式校验
- ILogger 自定义请求过程日志
- 局部 mock / 全局 mock 能力
- 长请求 loading
- 自定义响应值格式.
插件能力
- serialize-data | (默认集成) 基于
content-type
属性, 序列化数据 - serialize-url | (默认集成) url 检查&修复, 去除重复
/
. 基于urlFormat
参数启用 - env | 提供标准化环境识别协议
- dynamic-proxy | 请求动态代理 (需要
@ysfe/vue-default-config
支持) - mock | 全局 mock/局部 mock 切换
- loading | 请求过程 loading
- filter-null-value | 空参数过滤
- signature | 请求签名
- transform-request | 扩展请求前置处理操作
- transform-response | 扩展响应前置处理操作
- serialize-data | (默认集成) 基于
支持
构造参数 (IRequestOptions)
AxiosRequestOptions 接口扩展, 参数类型见接口
| 参数 | 描述 | 类型 | 默认值 | 可选 | | ------------ | ----------------------- | ----------------------------------- | ------ | ---- | | urlFormat | 是否启用 url 序列化检查 | boolean | true | ✅ | | mock | 是否启用 mock | boolean | - | ✅ | | logger | 自定义日志(工厂方法) | ILogger | - | ✅ | | loading | loading 插件支持 | ILoadingFactory | - | ✅ | | responseData | 响应数据格式 | TResponseData | 'data' | ✅ | | only | 请求防抖开关 | TOnly | - | ✅ | | max | 并发请求数限制开关 | number ( >= 0 ) | - | ✅ |
方法
提供链式调用的插件引用, 以及常用请求接口支持, 参数类型见接口
use params -
(plugin: IPlugin)
get params -
(url: string, params: any, options: IRequestOptions)
post params -
(url: string, data:any, options: IRequestOptions)
sendBeacon params -
(url: string, params: any)
IRequestOptions - 接口声明
appendHeader params -
(key:string, value:any)
setHeaders params -
(headers: {[key:string]:any})
注: get,post 差异参考 axios, 分别作用于请求的
params
、data
属性注: sendBeancon 仅能发送简短请求, 请求参数一定要简短, 否则会产生失败请求.
| method | 描述 | 参数 | | ------------ | --------------------------------------------------------- | ----------------------- | | use | 加载插件, 插件需要实现 IPlugin 接口 (允许链式调用) | use params | | appendHeader | 添加 header | appendHeader params | | removeHeader | 移除 header | string | | setHeaders | 设置 headers | setHeaders params | | cancelAll | 中断所有请求, 一般用于切换页面时, 中止未完成请求 | - | | request | 发送请求, 请求发送的默认方法 | IRequestOptions | | get | 发送 get 请求 | get params | | post | 发送 post 请求 | post params | | head | 发送 head 请求 | get params | | options | 发送 options 请求 | get params | | delete | 发送 delete 请求 | get params | | put | 发送 put 请求 | post params | | patch | 发送 patch 请求 | post params | | sendBeacon | 通过 navigator.sendBeacon()发出简短请求, 一般用于埋点上报 | sendBeacon params |
插件
通过切面编程方式, 扩展 axios 能力 , 参数类型见接口
插件使用参考: 使用参考
- env parmas -
(envs: IEnv | Array<IEnv>, envName?: TEnvName)
- loading parmas -
(handler: (status: boolean) => void, delayTime: number = 500)
delayTime
: 毫秒(ms)
- fnv params -
(filterEmptyString?: boolean)
filterEmptyString
: 是否过滤空字符串, (即,过滤字符串为''
场景)
- signature params -
(options: ISignatureOptions = { key: 'sign' })
- transformRequest parmas -
(handler: ITransformRequest)
- transformResponse parmas -
(handler: ITransformResponse)
- errorHandler parmas -
(handler: IErrorHandler)
- dynamicProxy params -
(proxyPath?: string)
proxyPath
: 自定义代理路径
注:
dynamic-proxy
动态代理插件仅在'process.env.NODE_ENV==="development"'
场景下生效
| 插件 | 描述 | 默认集成 | 参数 |
| ------------------ | ------------------------------------------------------- | -------- | ---------------------------- |
| serialize-data | 基于 content-type
属性, 序列化数据 | ✅ | - |
| serialize-url | url 检查&修复, 去除重复 /
. 基于urlFormat
参数启用 | ✅ | - |
| env | 提供标准化环境识别协议 | - | env params |
| dynamic-proxy | 请求动态代理 (需要 @ysfe/vue-default-config
支持) | - | dynamicProxy params |
| mock | 注入 全局/局部 mock 能力, 启用开关依赖IRequestOptions
| - | - |
| loading | 请求过程 loading | - | loading params |
| filter-null-value | 空参数过滤 | - | fnv params |
| signature | 请求签名 | - | signature params |
| transform-request | 标准化请求前置处理操作 | - | transformRequest params |
| transform-response | 标准化响应前置处理操作 | - | transformResponse params |
| error-handler | 标准化异常处理操作 | - | errorHandler parmas |
接口
IData
export interface IData {
[key: string]: any
}
IEnv
/** 环境名 */
export type TEnvName = 'production' | 'test' | 'dev' | 'local' | string
/** 环境配置 | 接口定义 */
export interface IEnv {
/** 环境名, 支持重名, 及 `test1`、`dev1`等 */
name: TEnvName
/** 环境启用条件
* @description Request工具根据 rule规则定义,
* @type {string} 基于 host 匹配, 当host相同时, 启用.
* @type {RegExp} 正则匹配, rule.test(location.href), 使用正则匹配url, 当满足规则时, 使用当前环境配置
* - 示例: //api.server.com/xxx -> /api\.server\.com/
* @type {() => boolean} 自定义环境判断 Factory Function. 当返回值为true时, 启用当前环境
*/
rule: string | RegExp | (() => boolean)
/** 请求地址前缀 */
baseURL: string
/** mock地址
* @description mock地址, 当启用 mock = true 时, 启用 mock 环境
*/
mockURL?: string
/** 动态代理, 来源路径. 用于本地开发时, 绕过跨域限制
* @description 仅 NODE_ENV==='production' 时, 可用.
*/
referer?: string
/** 环境优先级, 当同时满足多条环境规则时, 根据优先级大小选择环境, 默认则根据环境定义顺序, 选择环境 */
order?: number
}
ILoadingFactory
/** loading 操作处理接口 */
export interface ILoadingFactory {
/** loading 切换处理方法 */
handler: (status: boolean) => void
/** 延迟显示时间, 默认500毫秒, 小于等于 0ms, 则被忽略 */
delayTime: number
}
ILogger
/**
* 指示日志消息的严重性。
* 日志级别按严重性递增的顺序排列。所以“Debug”比“Trace”等更严重。
*/
export enum LogLevel {
/** 极低严重性诊断消息的日志级别. */
Trace = 0,
/** 调试错误. */
Debug = 1,
/** 消息. */
Information = 2,
/** 警告. */
Warning = 3,
/** 错误. */
Error = 4,
/** 严重错误. */
Critical = 5,
/** 最高日志级别。在配置日志记录以指示不应发出日志消息时使用. */
None = 6
}
export interface ILogger {
/** Called by the framework to emit a diagnostic message.
*
* @param {LogLevel} logLevel The severity level of the message.
* @param {string} message The message.
*/
log(...msg: LogLevel | any): void
}
IOnly
export interface IOnlyOption {
type?: boolean | 'merge' | 'error'
/** 请求延迟, 用来避免请求处理速度较快情况下的并发请求 */
delay?: number
/** 错误消息, 默认: '您的操作太快了' */
message?: string
}
export type TOnly = boolean | 'merge' | 'error' | IOnlyOption
IPlugin
/** 插件接口 */
export type IPlugin = {
/** 插件名, 唯一属性 */
pluginName: string
/** 处理方法 */
handler: (axios: AxiosInstance, plugins?: Array<string>) => void
}
IRequestOptions
export interface IRequestOptions extends AxiosRequestConfig {
/** 请求防抖 - 唯一请求, 默认: 'merge', 可通过 设置 false 关闭.
* @param {'merge'| 'skip' | 'error'} type 防抖方式
* - merge | 合并重复请求
* - skip | 出现重复请求时, 忽略
* - error | 出现重复请求时, 抛出异常
* @param {number} delay 请求时延, 通过延时函数, 将在一定时间段内发起的请求进行合并, 对节约请求资源很有帮助
* @param {Function} checker 自定义重复请求检查方法
*/
only?: TOnly
/** 并发请求数限制, 默认: 不限制 */
max?: number
/** 是否启用 url 格式校验, 默认: true */
urlFormat?: boolean
/** 自定义日志工具 */
logger?: ILogger
/** 启用mock能力, 需要依赖 `request.use(mock())`
* @description |
* - 作为全局配置时, 启用全局mock能力
* - 作为请求参数时, 启用局部mock能力
*/
mock?: boolean
/** 请求loading */
loading?: ILoadingFactory
/** 响应数据格式
* @param {'data'| 'origin'} responseData 防抖方式
* - data | 返回 res.data
* - origin | 返回 res
*/
responseData?: TResponseData
}
ISignatureOptions
/** 请求签名参数 */
export interface ISignatureOptions {
/** 签名字段, 默认: sign */
key?: 'sign' | 'signature' | string
/** 盐值 | 用于参数加盐计算
* @type {string} 盐值字段, 默认附加在结尾
* @type {IData} 传入盐值内容, 附加至对象结尾.
* @type {(data?:IData)} 工厂方法, 通过自定义方法, 向参数对象写入盐值
*
* @description 注: 加盐操作, 在参数排序后进行, 默认附加在参数最后一位. 如果需要参与排序, 那么需要通过工厂方法, 重新计算参数顺序
*/
salt?: string | IData | ((data?: IData) => IData)
/** 是否启用参数排序, 可自定义参数排序方法, 默认: true */
sort?: boolean | ((key1: string, key2: string) => number)
/** 签名算法, 默认: md5 */
sign?: 'md5' | 'sha1' | 'sha256' | ((serializeData: string, originData?: any) => string)
/** 是否禁用过滤空值操作 */
disableFilterNullValue?: boolean
}
ITransformRequest
/** 请求参数转换处理方法 */
export type ITransformRequest = (req: IRequestOptions) => IRequestOptions | Promise<IRequestOptions> | void
ITransformResponse
export type ITransformResponse = (
status: number,
code: number,
data: any,
response: AxiosResponse
) => Promise<void> | void
IErrorHandler
/** 异常处理
* @description 如果中止请求, 请抛出 throw new Error('request about')
*/
export type IErrorHandler = (e: Error | string) => Promise<void> | void
TResponseData
/** 响应数据格式
* @param {'data'| 'origin'} responseData 防抖方式
* - data | 返回 res.data
* - origin | 返回 res
*/
export type TResponseData = 'data' | 'origin'
安装
- 执行
yarn add @ysfe/request
使用参考
Env.ts 定义
/** 交易虎 后端接口配置 */
export const envs: Array<IEnv> = [
{
name: 'production',
rule: () => true,
referer: 'http://www.fe.com',
baseURL: '//server.xxx.com',
order: -1
},
// 预发环境
{
name: 'pre',
rule: /test\.fe\.com/,
referer: 'http://test.fe.com',
baseURL: '//server-pre.xxx.com'
},
// 本地调试&开发环境部署
{
name: 'dev',
rule: /(www\.fe\.com|localhost|127\.0\.0\.1)/,
referer: 'http://www.fe.com',
baseURL: '//server.fe.com'
order: process.env.NODE_ENV !== 'production' ? 1 : -1
}
]
定义请求工具
/** 创建请求处理工具 */
export const createRequest = (
logger: ILogger,
envName?: 'production' | 'pre' | 'test' | 'test2' | 'dev' | 'dev2'
): Request<IResponseData> => {
return (
new Request<IResponseData>({
headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
logger,
only: true,
mock: false // 当使用全局 mock 时, 将此项修改为 true
})
.use(env(envs, envName)) // 注入环境变量
.use(mock()) // 注入mock
.use(dynamicProxy()) // 注入动态代理
.use(filterNullValue()) // 注入请求空值过滤
// 切换loading显示, 采用默认的 500ms等待时间
.use(
loading((status: boolean) => {
// TODO 切换loading 显示
})
)
// 附加请求参数
.use(
transformRequest((req: IRequestOptions) => {
// 请求前额外附加header
// TODO 通过 getNativeHeader 获取 请求headers
const headers: any = {}
Object.assign(req.headers, headers)
})
)
// 响应处理
.use(
transformResponse((status: number, code: number, data: any) => {
// ? http 状态码 >= 400, 表示请求出错. 弹出报错信息即可
if (status >= 400) throw new Error('请求出错了')
// ? 正常请求
if ([0].includes(code)) return
// ? 未登录
if ([302].includes(code)) {
Cookie.remove('token', { expires: new Date().getTime() + 50 * 30 * 24 * 60 * 1000 * 1000 })
// TODO 延迟 1000ms后, replace 到登录页
}
if ([undefined, 53].includes(code)) {
console.log('outSide interface (example => upload)')
return
}
throw data
})
)
)
}
自定义插件
/** 定义一个插件
* @description 可以给定自定义参数
*/
export const plugin = (): IPlugin => {
return {
pluginName: '[plugin name]',
handler: (axios: AxiosInstance) => {
// TODO 基于 axios 规范, 对 axios 对象进行扩展
}
}
}
// 使用
const requst: Request = new Request().use()
// 执行请求
request.post('/xxx')