npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ysfe/request

v1.4.10

Published

宇石前端 - 基于 axios 的 Http 请求库扩展

Downloads

4

Readme

@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')