@baseh/h-request
v1.0.0
Published
前端请求库封装
Maintainers
Readme
src/utils/request.ts:
import { inject, createFetchRequestor } from 'request-library';
// 创建请求器
const requestor = createFetchRequestor(import.meta.env.VITE_API_BASE_URL || '');
// 添加请求拦截器(添加 token)
requestor.on('beforeRequest', (config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers = {
...config.headers,
'Authorization': `Bearer ${token}`
};
}
});
// 添加响应拦截器(处理错误)
requestor.on('error', (error, config) => {
console.error('请求错误:', error);
// 可以在这里处理统一错误,比如跳转到登录页
});
// 注入请求器
inject(requestor);
export default requestor;
在 main.ts 中引入:
import { createApp } from 'vue';
import App from './App.vue';
import './utils/request'; // 初始化请求库
createApp(App).mount('#app');
前端请求库
一个完整的前端请求库封装方案,提供请求缓存、请求幂等、请求并发、请求串行等高级功能。
📦 项目结构
request-library/
├── src/
│ ├── types/ # 类型定义
│ │ └── index.ts
│ ├── request-imp/ # 请求实现层(基于fetch)
│ │ └── fetch-imp.ts
│ ├── request-core/ # 请求核心层
│ │ ├── index.ts # 缓存、幂等、并发、串行、重试
│ │ └── store.ts # 缓存存储实现
│ ├── request-bus/ # 请求业务层
│ │ ├── index.ts
│ │ ├── templet/ # 样板代码(自动生成)
│ │ └── patch/ # 补丁代码(手动修改)
│ └── index.ts # 主入口
├── examples/ # 使用示例
├── package.json
├── tsconfig.json
└── README.md🏗️ 架构设计
采用三层架构设计,从下往上依次是:
请求实现层(request-imp)
- 提供请求基本功能
- 支持多种实现方式:fetch、XHR、axios
- 通过依赖倒置原则与上层解耦
- 可以灵活切换实现方式,无需修改业务代码
请求核心层(request-core)
- 提供网络上层控制功能
- 包括:请求缓存、请求幂等、请求并发、请求串行、请求重试
请求业务层(request-bus)
- 封装业务接口
- 接入公司内部协议规范
- 向外提供业务接口 API
🚀 快速开始
安装
npm install
npm run build基础使用
import { inject } from './src';
// 可以选择不同的实现方式
import { createFetchRequestor } from './src/request-imp/fetch-imp';
import { createXHRRequestor } from './src/request-imp/xhr-imp';
import { createAxiosRequestor } from './src/request-imp/axios-imp';
// 方式1:使用 Fetch(推荐,现代浏览器)
const requestor = createFetchRequestor('https://api.example.com');
inject(requestor);
// 方式2:使用 XHR(兼容性好)
// const requestor = createXHRRequestor('https://api.example.com');
// inject(requestor);
// 方式3:使用 Axios(功能丰富,需要安装 axios)
// const requestor = createAxiosRequestor('https://api.example.com');
// inject(requestor);
// 使用请求(无论使用哪种实现,API 完全一致)
const response = await requestor.get('/api/articles');
console.log(response.data);业务接口使用
import { publishArticle, getArticles } from './src/request-bus';
// 发布文章(自动应用幂等性)
await publishArticle({
title: '我的文章',
content: '文章内容...'
});
// 获取文章列表(自动应用缓存)
const articles = await getArticles(1, 10);🚀 高级功能
除了基础功能,还提供了更多高级功能:
请求去抖(Debounce)
import { createDebounceRequestor } from 'request-library';
const debouncedSearch = createDebounceRequestor(500);
// 500ms内多次调用,只执行最后一次
debouncedSearch.get('/api/search', { params: { keyword: 'test' } });请求节流(Throttle)
import { createThrottleRequestor } from 'request-library';
const throttledLoad = createThrottleRequestor(1000);
// 1秒内无论调用多少次,只执行一次
window.onscroll = () => throttledLoad.get('/api/load-more');请求去重(Deduplication)
import { createDedupeRequestor } from 'request-library';
const dedupeRequestor = createDedupeRequestor();
// 同时发起多个相同请求,只发送一次,共享结果
Promise.all([
dedupeRequestor.get('/api/user/123'),
dedupeRequestor.get('/api/user/123'),
dedupeRequestor.get('/api/user/123')
]);请求重试策略(Retry Strategy)
import { createRetryStrategyRequestor } from 'request-library';
const retryRequestor = createRetryStrategyRequestor({
maxRetries: 3,
retryDelay: (attempt) => Math.pow(2, attempt) * 1000, // 指数退避
shouldRetry: (error) => error.response?.status >= 500,
onRetry: (attempt, error) => console.log(`重试第${attempt}次`)
});请求限流(Rate Limiting)
import { createRateLimitRequestor } from 'request-library';
const rateLimitedRequestor = createRateLimitRequestor({
maxRequests: 10,
window: 1000 // 每秒最多10个请求
});更多高级功能请查看 高级功能文档
📖 详细文档
- 快速开始 - 5分钟快速上手指南
- 使用指南 - 在新项目中使用和扩展请求库的完整指南
- 集成示例 - Vue 3 + TypeScript 完整集成示例
- 实现方式选择 - Fetch/XHR/Axios 选择指南
- 高级功能 - 25种高级请求功能需求清单
✨ 核心功能
1. 请求缓存
创建带有缓存的请求,支持自定义缓存键和失效策略。
import { createCacheRequestor } from './src';
const req = createCacheRequestor({
duration: 1000 * 60 * 5, // 缓存5分钟
key: (config) => `${config.method}:${config.url}`,
persist: false // 使用内存缓存
});
// 第一次请求
const data1 = await req.get('/api/articles');
// 第二次请求(使用缓存)
const data2 = await req.get('/api/articles');2. 请求幂等
保证幂等性请求不会重复提交。
import { createIdempotentRequestor } from './src';
const req = createIdempotentRequestor();
// 多次调用相同的请求,只会实际发送一次
await req.post('/api/payment', { orderId: '123', amount: 100 });
await req.post('/api/payment', { orderId: '123', amount: 100 }); // 使用缓存3. 请求并发控制
限制同时进行的请求数量。
import { createParallelRequestor } from './src';
const req = createParallelRequestor({ maxCount: 3 }); // 最多3个并发
// 这10个请求会以3个为一组并发执行
const promises = Array.from({ length: 10 }, (_, i) =>
req.get(`/api/data/${i}`)
);
await Promise.all(promises);4. 请求串行控制
确保请求按顺序执行。
import { createSerialRequestor } from './src';
const req = createSerialRequestor();
// 这些请求会按顺序执行
await req.post('/api/step1');
await req.post('/api/step2');
await req.post('/api/step3');5. 请求重试
自动重试失败的请求。
import { createRetryRequestor } from './src';
const req = createRetryRequestor(3, 1000); // 最多重试3次,每次间隔1秒
try {
const data = await req.get('/api/unstable-endpoint');
} catch (error) {
console.error('请求失败:', error);
}6. 事件监听
监听请求生命周期事件。
const req = requestor;
// 监听请求前事件
req.on('beforeRequest', (config) => {
console.log('请求即将发送:', config.url);
// 添加认证token
config.headers = config.headers || {};
config.headers['Authorization'] = 'Bearer token';
});
// 监听响应事件
req.on('responseBody', (config, response) => {
console.log('收到响应:', response.status, response.data);
});
// 监听错误事件
req.on('error', (error, config) => {
console.error('请求错误:', error.message);
});📝 API 文档
Requestor 接口
所有请求器都实现了 Requestor 接口:
interface Requestor {
get<T>(url: string, options?: RequestOptions): Promise<Response<T>>;
post<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
put<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
delete<T>(url: string, options?: RequestOptions): Promise<Response<T>>;
patch<T>(url: string, data?: any, options?: RequestOptions): Promise<Response<T>>;
on(event: string, handler: Function): void;
off(event: string, handler: Function): void;
emit(event: string, ...args: any[]): void;
}RequestOptions
interface RequestOptions {
headers?: Record<string, string>;
params?: Record<string, any>;
body?: any;
timeout?: number;
auth?: boolean;
[key: string]: any;
}CacheOptions
interface CacheOptions {
key?: (config: RequestConfig) => string;
duration?: number;
isValid?: (key: string, config: RequestConfig) => boolean | Promise<boolean>;
persist?: boolean;
}🔧 高级用法
组合使用多个功能
import {
createFetchRequestor,
inject,
createCacheRequestor,
createParallelRequestor
} from './src';
// 创建基础请求器
const baseRequestor = createFetchRequestor('https://api.example.com');
// 添加缓存功能
const cachedRequestor = createCacheRequestor({
duration: 1000 * 60 * 5
})(baseRequestor);
// 添加并发控制
const finalRequestor = createParallelRequestor({ maxCount: 3 })(cachedRequestor);
inject(finalRequestor);自定义缓存存储
import { CacheStore } from './src/types';
import { useCacheStore } from './src/request-core/store';
// 使用持久化存储
const store = useCacheStore(true); // true 表示使用 localStorage
// 自定义存储
class CustomStore implements CacheStore {
// 实现接口方法...
}📚 业务层使用
样板代码和补丁机制
业务层采用样板代码 + 补丁的机制:
templet/目录:自动生成的样板代码patch/目录:手动修改的补丁代码(会覆盖样板代码)
// templet/article.ts(自动生成)
export const publishArticle = () => {
// 基础实现
};
// patch/article.ts(手动修改)
export const publishArticle = () => {
// 添加额外逻辑,如认证token
};🎯 设计亮点
- 依赖倒置原则(DIP):核心层不依赖具体实现,通过接口抽象实现灵活切换
- 三层架构:清晰的职责分离,易于维护和扩展
- 事件系统:支持请求生命周期事件监听
- 类型安全:完整的 TypeScript 类型支持
- 组合式设计:各种功能可以灵活组合使用
📄 许可证
MIT
🤝 贡献
欢迎提交 Issue 和 Pull Request!
