@cmchu/request-enhancer
v0.0.1
Published
A powerful request enhancement library with middleware support
Downloads
6
Maintainers
Readme
HTTP 请求增强工具库
一个基于 TypeScript 构建的强大且灵活的 HTTP 请求增强工具库。支持自定义请求适配器,支持中间件机制,可以轻松集成到任何 HTTP 客户端。
特性
- 🚀 灵活的请求适配器系统,支持不同的 HTTP 客户端
- 🔄 请求/响应拦截器
- 🎯 完整的 TypeScript 支持
- 🔌 插件化的中间件系统
- 🛠️ 内置中间件:
- 🚫 支持请求取消
- 💾 支持请求缓存
- 🔄 支持请求重试
- 📊 支持请求进度监控
- ⚡ 支持请求节流和防抖
- 📝 支持请求日志记录
- 支持自定义中间件
安装
npm install @cmchu/request-enhancer快速开始
import { createRequest, createCacheMiddleware, createRetryMiddleware, createLoggerMiddleware } from '@cmchu/request-enhancer';
// 创建请求实例
const request = createRequest({
// 使用自定义适配器
request: async (config) => {
// 实现你的请求逻辑
return response;
}
}, {
baseURL: 'https://api.example.com',
timeout: 5000,
});
// 添加中间件
request
.use(createCacheMiddleware()) // 使用缓存中间件
.use(createRetryMiddleware()); // 使用错误重试中间件
// 发起请求
const response1 = await request.get('/users');
// 发起带数据的 POST 请求
const response2 = await request.post('https://api.example.com/data', {
name: 'John',
age: 30
});
// 单个请求注册 日志中间件
// 仍然会使用 createCacheMiddleware 和 createRetryMiddleware 中间件
const response3 = await request.use(createLoggerMiddleware(), 3).get('/api/demo');
请求取消
支持取消单个请求或所有请求:
// 取消单个请求
request.cancel('request-id');
// 取消所有请求
request.cancel();中间件
中间件类型
/**
* 中间件接口
* 定义了中间件的基本结构
*/
export interface Middleware {
/** 中间件名称,用于标识和移除中间件 */
name: string;
/** 请求中间件,在发送请求前执行 */
request?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
/** 响应中间件,在收到响应后执行 */
response?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
/** 错误中间件,在请求失败时执行 */
error?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
}中间件优先级
中间件按优先级顺序执行,优先级数字越大越先执行:
request.use(middleware1, 100); // 优先级 100
request.use(middleware2, 50); // 优先级 50
request.use(middleware3, 0); // 优先级 0中间件使用
import { createRequest, createCacheMiddleware, createRetryMiddleware } from '@cmchu/request-enhancer';
const request = createRequest({
// 自定义配置
config: {
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
},
// 启用默认中间件选项
middlewares: {
cache: true, // 开启 数据缓存中间件
retry: true, // 开启 错误重试中间件
logger: true // 开启 请求日志中间件
}
});内置中间件
日志中间件 (Logger)
- 记录请求和响应的详细信息:
- 适用场景:
- 开发调试;
- 问题排查;
- 性能监控。
interface LoggerOptions {
/** 是否输出请求信息,默认 true */
logRequest?: boolean;
/** 是否输出响应信息,默认 true */
logResponse?: boolean;
/** 是否输出错误信息,默认 true */
logError?: boolean;
/** 日志前缀 */
prefix?: string;
}
request.use(createLoggerMiddleware({
logRequest: true, // 记录请求
logResponse: true, // 记录响应
logError: true, // 记录错误
prefix: '[request-]' // 日志前缀
}));
- 示例:单个请求的日志
request.use(createLoggerMiddleware())
request.request({
url: '/api/login',
method: 'GET',
log: {
logRequest: true, // 记录请求
logResponse: false, // 不记录响应
logError: false, // 记录错误
prefix: '[request-login-]' // 日志前缀
}
})缓存中间件 (Cache)
- 用于缓存请求响应数据,提高应用性能。和其他中间件配合使用,可以达到意想不到的效果。
interface CacheOptions {
// 是否启用缓存 默认值:false
enableCache?: boolean;
// 缓存过期时间(毫秒) 默认值:5分钟
ttl?: number;
// 最大缓存条目数 默认值:100
maxSize?: number;
// 是否启用压缩 默认值:true
enableCompression?: boolean;
// 缓存版本号 用于在版本更新时清除缓存
version?: string;
// 是否在版本更新时清除缓存 默认值:true
clearOnVersionChange?: boolean;
// 缓存的配置
cache?: {
// 自定义缓存键生成方法
getCacheKey: (config: RequestConfig) => string;
// 缓存的键值
keys?: () => Promise<string[]>;
// 自定义缓存设置方法
setCache: (key: string, data: unknown) => Promise<void>;
// 自定义缓存获取方法
getCache: (key: string) => Promise<CacheEntry | null>;
// 自定义缓存清除方法
clearCache: (key?: string) => Promise<void>;
},
// localforage 配置,如果设置了cache 配置,该配置将不起作用
storageConfig?: {
name?: string;
storeName?: string;
size?: number;
driver?: string[];
};
}
// 基础配置
request.use(createCacheMiddleware({
enableCache: true, // 启用缓存
enableCompression: true // 启用压缩
ttl: 5 * 60 * 1000, // 缓存时间
maxSize: 100, // 最大缓存条目数
version: '1.0.0', // 缓存版本
clearOnVersionChange: true // 版本改变时清除缓存
}));
- 示例:请求的缓存
request.use(createCacheMiddleware({
enableCompression: true // 启用压缩
ttl: 5 * 60 * 1000, // 缓存时间
version: '1.0.0', // 缓存版本
clearOnVersionChange: true // 版本改变时清除缓存
}))
request.request({
url: '/api/data',
method: 'GET',
cache: {
enableCache: true // 启用缓存
}
})- 缓存工作原理
- 请求拦截:拦截GET请求,检查是否启用缓存
- 缓存键生成:根据请求配置生成唯一的缓存键
- 缓存查找:在缓存存储中查找是否存在有效缓存
- 缓存命中:如果找到有效缓存,直接返回缓存数据
- 缓存未命中:如果未找到缓存,执行实际请求
- 缓存存储:将响应数据存储到缓存中,设置过期时间
- 缓存清理:定期清理过期缓存,维护缓存大小限制
适用场景
频繁请求的静态数据(如配置信息、用户资料)
不经常变化的数据(如商品分类、地区信息)
需要提高响应速度的场景(如搜索建议、热门内容)
离线应用的数据缓存
减少服务器压力的场景
重试中间件 (Retry)
- 自动重试失败的请求。
interface RetryOptions {
/** 是否启用重试,默认false */
enableRetry?: boolean;
/** 最大重试次数,默认3次 */
maxRetries?: number;
/** 重试延迟时间(毫秒),默认200ms */
retryDelay?: number;
/** 重试条件函数,返回true表示需要重试 */
shouldRetry?: (error: any, context: MiddlewareContext) => boolean;
}
request.use(createRetryMiddleware({
// 是否启用重试
enableRetry: true,
// 重试次数
maxRetries: 3,
// 重试延迟
retryDelay: 1000,
// 重试条件函数
shouldRetry: (error: any) => error?.response?.status !== 200
}));- 示例:请求的重试
request.use(createRetryMiddleware({
maxRetries: 3,
retryDelay: 1000,
}))
request.request({
url: '/api/data',
method: 'GET',
retry: {
enableRetry: true,
shouldRetry: (error: any) => error?.response?.status !== 200
}
})- 重试工作原理
- 错误捕获:捕获请求执行过程中的错误
- 重试判断:根据shouldRetry函数判断是否需要重试
- 重试计数:检查当前重试次数是否超过最大限制
- 延迟等待:等待指定的延迟时间后再次尝试
- 请求重试:重新发起请求,更新重试计数
- 成功处理:如果重试成功,返回响应结果
- 失败处理:如果达到最大重试次数仍失败,抛出最终错误
适用场景
网络不稳定的环境(如移动网络、弱网环境)
服务器临时故障的恢复
需要提高请求成功率的场景
关键业务操作的容错处理
用户体验优化(减少用户手动重试)
节流中间件 (Throttle)
- 限制请求频率: 在一定时间内,多次触发同一请求,只执行第一次。
interface ThrottleOptions {
/** 是否启用节流,默认false */
enableThrottle?: boolean,
/** 时间间隔(毫秒),默认1000ms */
interval?: number;
}
request.use(createThrottleMiddleware({
enableThrottle: true, // 启用节流
interval: 200, // 时间间隔 200 毫秒
}));- 示例:请求的节流
request.use(createThrottleMiddleware({
enableThrottle: false, // 默认不启用节流
interval: 200, // 时间间隔 200 毫秒
}))
request.request({
url: '/api/data',
method: 'GET',
throttle: {
enableThrottle: true
}
})- 节流工作原理
- 请求拦截:拦截相同请求,检查是否在节流时间窗口内
- 时间窗口判断:判断距离上次执行是否超过指定间隔
- 首次执行:如果是首次请求或超过时间窗口,立即执行
- 结果缓存:缓存第一次请求的响应结果
- 后续请求处理:后续相同请求直接返回缓存结果
- 时间窗口重置:时间窗口结束后,允许新的请求执行
- 状态清理:清理过期的节流状态
适用场景
搜索框输入节流(如搜索建议)
按钮点击防重复提交
滚动事件处理(如无限滚动加载)
窗口大小调整事件
需要限制执行频率的用户交互
防抖中间件 (Debounce)
- 限制请求频率: 在一定时间内,多次触发同一请求,只执行最后一次。
interface DebounceOptions {
/** 是否启用防抖,默认false */
enableDebounce?: boolean,
/** 延迟时间(毫秒),默认300ms */
delay?: number;
}
request.use(createDebounceMiddleware({
enableDebounce: true, // 启用防抖
delay: 200, // 延迟时间 200 毫秒
}));- 示例:请求的防抖
request.use(createDebounceMiddleware({
enableDebounce: false, // 默认不启用防抖
delay: 200, // 延迟时间 200 毫秒
}))
request.request({
url: '/api/data',
method: 'GET',
debounce: {
enableDebounce: true,
delay: 500, // 延迟时间 500 毫秒
}
})- 防抖工作原理
- 请求拦截:拦截相同请求,检查是否存在等待中的请求
- 定时器管理:为每个请求设置延迟定时器
- 请求取消:如果新请求到达,取消之前的定时器
- 延迟执行:等待指定的延迟时间后执行请求
- 回调队列管理:管理等待中的请求回调函数
- 结果分发:请求完成后,将结果分发给所有等待的请求
- 状态清理:清理防抖状态,准备处理下一个请求
适用场景
搜索框输入防抖(如实时搜索)
表单验证防抖
窗口大小调整事件
需要等待用户操作完成的场景
减少无效请求的网络开销
批处理中间件 (batch)
- 将多个请求合并为一个请求,减少网络开销,提高性能。适用于需要批量获取数据的场景,如用户列表、商品信息等。
interface BatchOptions {
/** 是否启用批处理,默认false */
enable?: boolean;
/** 合并请求的函数 */
merge?: MergeFn;
}
interface BatchMiddlewareOptions {
/** 最大批处理大小,默认10 */
maxBatchSize?: number;
/** 最大等待时间(毫秒),默认100ms */
maxWaitTime?: number;
/** 合并请求的函数 */
merge?: MergeFn;
}
// 合并请求参数类型
type MergeRequestFn = (type: 'request', data: RequestConfig[]) => RequestConfig
// 分解响应参数类型
type MergeResponseFn = (type: 'response', data: Response<any>) => Response<any>[]
type MergeFn = MergeRequestFn & MergeResponseFn;- 基础配置
request.use(createBatchMiddleware({
maxBatchSize: 10, // 最大批处理大小
maxWaitTime: 100, // 最大等待时间
merge: (type, data) => {
if (type === 'request') {
// 合并多个请求配置为一个请求配置
return {
url: '/api/batch',
method: 'POST',
data: { requests: data }
};
} else {
// 将响应数据分解为多个响应
return data.data.responses;
}
}
}));- 示例:请求的批处理
request.use(createBatchMiddleware({
maxBatchSize: 5,
maxWaitTime: 200
}))
// 发起多个批处理请求
const promises = [
request.request({
url: '/api/user/1',
method: 'GET',
batch: {
enable: true,
merge: (type, data) => {
if (type === 'request') {
return {
url: '/api/batch/users',
method: 'POST',
data: { userIds: data.map(req => req.url.split('/').pop()) }
};
} else {
return data.data.users;
}
}
}
}),
request.request({
url: '/api/user/2',
method: 'GET',
batch: { enable: true }
}),
request.request({
url: '/api/user/3',
method: 'GET',
batch: { enable: true }
})
];
const results = await Promise.all(promises);- 批处理工作原理
- 请求入队:启用批处理的请求进入队列
- 等待触发:等待队列达到最大大小或超时时间
- 请求合并:使用merge函数将多个请求合并为一个
- 执行请求:执行合并后的请求
- 响应分解:使用merge函数将响应分解为多个响应
- 结果分发:将分解后的响应分发给对应的原始请求
适用场景
批量获取用户信息、商品数据
减少API调用次数,提高性能
需要聚合多个数据源的场景
移动端网络优化
优先级队列中间件 (priority)
- 根据请求优先级控制请求的执行顺序,高优先级请求优先执行。适用于需要控制请求执行顺序的场景,如用户交互请求优先于后台任务。
interface PriorityOptions {
/** 是否启用优先级队列,默认false */
enable?: boolean;
/** 请求优先级,数字越大越先执行,默认0 */
priority?: number;
/** 请求超时时间(毫秒) */
timeout?: number;
}
interface PriorityMiddlewareOptions {
/** 最大并发请求数,默认5 */
maxConcurrent?: number;
/** 默认优先级,默认0 */
defaultPriority?: number;
/** 是否启用优先级公平性(相同优先级按FIFO处理),默认true */
enableFairness?: boolean;
}- 基础配置
request.use(createPriorityMiddleware({
maxConcurrent: 5, // 最大并发请求数
defaultPriority: 0, // 默认优先级
enableFairness: true // 启用优先级公平性
}));- 示例:请求的优先级控制
request.use(createPriorityMiddleware({
maxConcurrent: 3
}))
// 高优先级请求(优先级:100)
const highPriorityRequest = request.request({
url: '/api/critical',
method: 'POST',
data: { action: 'critical' },
priority: {
enable: true,
priority: 100, // 高优先级
timeout: 5000 // 5秒超时
}
});
// 中优先级请求(优先级:50)
const mediumPriorityRequest = request.request({
url: '/api/important',
method: 'GET',
priority: {
enable: true,
priority: 50 // 中优先级
}
});
// 低优先级请求(优先级:10)
const lowPriorityRequest = request.request({
url: '/api/normal',
method: 'GET',
priority: {
enable: true,
priority: 10 // 低优先级
}
});
// 无优先级请求(默认优先级:0)
const normalRequest = request.request({
url: '/api/background',
method: 'GET'
});- 优先级队列工作原理
- 请求入队:启用优先级的请求会进入优先级队列
- 优先级排序:队列按优先级从高到低排序,相同优先级按FIFO处理
- 并发控制:控制同时执行的请求数量,不超过maxConcurrent
- 请求执行:高优先级请求优先执行
- 队列更新:请求完成后从队列中移除,继续处理下一个请求
适用场景
用户交互请求需要优先处理(如搜索、表单提交)
关键业务操作需要高优先级(如支付、登录)
后台任务可以降低优先级(如数据同步、日志上传)
需要控制并发数量的场景
移动端网络资源管理
性能特点
时间复杂度:入队O(log n),出队O(1)
空间复杂度:O(n),n为队列长度
并发控制:精确控制同时执行的请求数量
优先级公平性:相同优先级按先进先出原则处理
进度中间件 (Progress)
- 监控请求上传和下载进度。
interface ProgressOptions {
/** 上传进度回调 */
onUploadProgress?: (progress: number) => void;
/** 下载进度回调 */
onDownloadProgress?: (progress: number) => void;
/** 是否在请求配置中包含进度回调 */
includeInConfig?: boolean;
}
request.use(createProgressMiddleware({
onUploadProgress: (progress) => {
console.log(`上传进度: ${progress}%`);
},
onDownloadProgress: (progress) => {
console.log(`下载进度: ${progress}%`);
}
}));请求配置
interface RequestConfig {
/** 请求URL */
url: string;
/** 请求方法,默认为GET */
method?: string;
/** 请求头 */
headers?: Record<string, string>;
/** 请求体数据 */
data?: any;
/** URL查询参数 */
params?: Record<string, any>;
/** 请求超时时间(毫秒) */
timeout?: number;
/** 请求ID 请求的唯一标识 */
requestId?: string;
/** 其他自定义配置项 */
[key: string]: any;
}响应数据
interface Response<T = any> {
/** 响应数据 */
data: T;
/** HTTP状态码 */
status: number;
/** HTTP状态文本 */
statusText: string;
/** 响应头 */
headers: Record<string, string>;
/** 原始请求配置 */
config: RequestConfig;
}API 参考
请求实例方法
request<T>(config: RequestConfig): Promise<Response<T>>- 发起请求的通用方法
- 支持泛型类型参数
- 返回 Promise 对象
get<T>(url: string, config?: RequestConfig): Promise<Response<T>>- 发起 GET 请求
- 支持查询参数
- 支持自定义配置
post<T>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>- 发起 POST 请求
- 支持请求体数据
- 支持自定义配置
put<T>(url: string, data?: any, config?: RequestConfig): Promise<Response<T>>- 发起 PUT 请求
- 支持请求体数据
- 支持自定义配置
delete<T>(url: string, config?: RequestConfig): Promise<Response<T>>- 发起 DELETE 请求
- 支持自定义配置
use(middleware: Middleware): void- 添加中间件
- 支持中间件优先级
- 支持链式调用
removeMiddleware(name: string): void- 移除指定名称的中间件
- 支持动态移除
cancel(requestIdOrConfig?: string | RequestConfig): void- 取消请求
- 支持通过请求ID取消
- 支持通过配置取消
- 支持取消所有请求
中间件开发
中间件接口
interface Middleware {
/** 中间件名称 */
name: string;
/** 请求中间件 */
request?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
/** 响应中间件 */
response?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
/** 错误中间件 */
error?: (context: MiddlewareContext, next: NextFunction) => Promise<void>;
}中间件上下文
interface MiddlewareContext {
/** 请求配置 */
config: RequestConfig;
/** 响应数据 */
response?: Response;
/** 错误信息 */
error?: Error;
/** 请求方法 */
request: RequestInstance['executeRequest'];
}Request类类型声明
/**
* Request类构造函数参数接口
*/
interface RequestConstructorParams {
/** 请求适配器,用于执行实际的HTTP请求 */
adapter: RequestAdapter;
/** 默认配置 */
config?: Partial<RequestConfig>;
}
/**
* Request类私有属性接口
*/
interface RequestPrivateProperties {
/** 中间件列表 */
middlewares: Array<{ middleware: Middleware; priority: number }>;
/** 默认配置 */
defaultConfig: Partial<RequestConfig>;
/** 请求适配器 */
adapter: RequestAdapter;
/** 请求取消控制器映射 */
abortControllers: Map<string, AbortController>;
}
/**
* Request类私有方法接口
*/
interface RequestPrivateMethods {
/**
* 合并请求配置
* @param config 请求配置
* @returns 合并后的配置
*/
mergeConfig(config: RequestConfig): RequestConfig;
/**
* 执行中间件
* @param type 中间件类型:'request' | 'response' | 'error'
* @param context 中间件上下文
* @returns Promise<void>
*/
executeMiddlewares(
type: 'request' | 'response' | 'error',
context: MiddlewareContext
): Promise<void>;
}
/**
* Request类完整类型声明
* 继承RequestInstance接口,并包含私有属性和方法
*/
type RequestClass = RequestInstance & RequestPrivateMethods & {
/** 私有属性 */
readonly _private: RequestPrivateProperties;
};适配器开发
适配器接口
interface RequestAdapter {
request<T = any>(config: RequestConfig): Promise<Response<T>>;
}完整类型导出
// 从包中导入所有类型
import type {
// 基础类型
RequestConfig,
Response,
RequestAdapter,
// 中间件相关
Middleware,
MiddlewareContext,
NextFunction,
// 请求实例
RequestInstance,
RequestClass,
// Request类相关
RequestConstructorParams,
RequestPrivateProperties,
RequestPrivateMethods,
// 创建选项
CreateRequestOptions
} from '@cmchu/request-enhancer';许可证
MIT
