@ysfe/request
TypeScript icon, indicating that this package has built-in type declarations

1.4.10 • Public • Published

@ysfe/request

Introduction

npm version NPM downloads

描述


基于 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 | 扩展响应前置处理操作



支持




构造参数 (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, 分别作用于请求的 paramsdata 属性

  • 注: 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')

Readme

Keywords

none

Package Sidebar

Install

npm i @ysfe/request

Weekly Downloads

0

Version

1.4.10

License

MIT

Unpacked Size

173 kB

Total Files

204

Last publish

Collaborators

  • wellfee
  • huanyansss