@kkfive/request
v0.3.0
Published
A self-used request encapsulation
Readme
@kkfive/request
一个基于 ky 的轻量级、类型安全的 HTTP 请求库
✨ 特性
- 🎯 类型安全 - 完整的 TypeScript 支持,提供优秀的类型推导
- 🔄 响应解析 - 三种响应模式(raw/body/data),自动解析和验证响应数据
- 🛡️ 错误处理 - 增强的 RequestError 类,提供 9 个辅助方法用于错误判断
- 🔌 灵活扩展 - 支持实例扩展(extend)和 Hooks 机制
- 📦 轻量级 - 基于 ky 封装,保持简洁和高性能
- 🎨 易于使用 - 简洁的 API 设计,符合直觉的使用方式
📦 安装
# pnpm
pnpm add @kkfive/request ky qs
# npm
npm install @kkfive/request ky qs
# yarn
yarn add @kkfive/request ky qs注意:
ky和qs是 peer dependencies,需要手动安装。
兼容性提示:推荐在 Node.js LTS (18+) 的 ESM 环境中使用;若仍在 CommonJS 项目中,可以直接
const { request } = require('@kkfive/request')。
🚀 快速开始
基础使用
import { Request } from '@kkfive/request'
// 创建请求实例
const request = new Request({
prefixUrl: 'https://api.example.com',
timeout: 10000,
})
// 发送 GET 请求
const data = await request.get('/users/1')
console.log('用户数据:', data)
// 发送 POST 请求
const newUser = await request.post('/users', {
name: '张三',
email: '[email protected]',
})最简调用(内置实例)
直接使用库内置的 request 实例即可完成一次请求,也可以配合 extend 派生新实例:
import { request } from '@kkfive/request'
const user = await request.get('/users/1', {
prefixUrl: 'https://api.example.com',
})
const authedRequest = request.extend({
headers: { Authorization: 'Bearer token' },
})响应解析器
自动解析和验证响应数据,支持三种模式:
const request = new Request({
prefixUrl: 'https://api.example.com',
responseParser: {
responseReturn: 'data', // 'raw' | 'body' | 'data'
codeField: 'code', // 业务状态码字段
dataField: 'data', // 数据字段
successCode: 0, // 成功状态码
errorMessageField: 'message',
},
})
// 自动提取 data 字段,验证业务状态码
const userData = await request.get('/users/1')
// userData 直接是 data 字段的内容错误处理
增强的 RequestError 类提供丰富的错误判断方法:
try {
const data = await request.get('/api/data')
console.log('数据:', data)
}
catch (error) {
const err = error as RequestError
if (err.isBusinessError) {
// 业务错误(HTTP 200 但业务 code 不匹配)
console.log('业务错误:', err.message)
}
else if (err.is4xxError()) {
// 4xx 客户端错误
if (err.isHttpError(401)) {
console.log('未授权,需要登录')
}
}
else if (err.is5xxError()) {
// 5xx 服务器错误
console.log('服务器错误,请稍后重试')
}
else if (err.isTimeout()) {
// 超时错误
console.log('请求超时')
}
// 格式化输出
console.log(err.toString())
// 输出: 业务错误 [500]: 接口响应失败
}实例扩展
使用 extend() 创建派生实例,继承并扩展配置:
// 创建基础实例
const baseRequest = Request.create({
prefixUrl: 'https://api.example.com',
timeout: 10000,
})
// 创建带认证的派生实例
const authRequest = baseRequest.extend({
headers: {
Authorization: 'Bearer your-token',
},
})
// 创建管理员派生实例
const adminRequest = authRequest.extend({
headers: {
'X-Admin-Token': 'admin-secret',
},
})📚 API 文档
Request 类
构造函数
new Request(options?: RequestOption)静态方法
Request.create(options?: RequestOption): Request- 创建新实例
实例方法
get<T>(url: string, config?: RequestOption): Promise<T>- GET 请求post<T>(url: string, data?: unknown, config?: RequestOption): Promise<T>- POST 请求put<T>(url: string, data?: unknown, config?: RequestOption): Promise<T>- PUT 请求patch<T>(url: string, data?: unknown, config?: RequestOption): Promise<T>- PATCH 请求delete<T>(url: string, data?: unknown, config?: RequestOption): Promise<T>- DELETE 请求head(url: string, config?: RequestOption): Promise<Response>- HEAD 请求options(url: string, config?: RequestOption): Promise<Response>- OPTIONS 请求extend(options: RequestOption): Request- 创建派生实例
RequestOption 配置
interface RequestOption {
// ky 的所有配置项
prefixUrl?: string
timeout?: number
headers?: Record<string, string>
// 扩展配置
params?: Record<string, any>
paramsSerializer?: 'brackets' | 'comma' | 'indices' | 'repeat'
responseParser?: ResponseParserOptions
makeErrorMessage?: (message: string, error: RequestError) => void
hooks?: {
beforeRequest?: Array<(request: Request, options: Options) => void>
afterResponse?: Array<(request: Request, options: Options, response: Response) => Response>
}
}ResponseParserOptions 配置
type ResponseParserOptions
= | { responseReturn: 'raw' } // 返回原始 Response 对象
| { responseReturn: 'body' } // 返回完整响应体
| {
responseReturn: 'data' // 提取数据字段并验证
codeField?: string // 业务状态码字段,默认 'code'
dataField?: string | ((res: any) => any) // 数据字段,默认 'data'
successCode?: number | string | ((code: any) => boolean) // 成功状态码,默认 0
errorCodeField?: string // 错误码字段
errorMessageField?: string | ((res: any) => string) // 错误信息字段
}RequestError 类
属性
message: string- 错误信息code?: string | number- 错误码raw?: any- 原始响应体response?: Response- 原始 Response 对象isBusinessError: boolean- 是否是业务错误options?: RequestOption- 请求配置
方法
isNetworkError(): boolean- 判断是否是网络错误isHttpError(status?: number): boolean- 判断是否是 HTTP 错误is4xxError(): boolean- 判断是否是 4xx 客户端错误is5xxError(): boolean- 判断是否是 5xx 服务器错误isTimeout(): boolean- 判断是否是超时错误toString(): string- 格式化错误信息toJSON(): object- 转换为 JSON 对象
📖 示例
查看 examples 目录获取更多详细示例:
- 01-basic-usage.ts - 基础使用示例
- 02-response-parser.ts - 响应解析器示例
- 03-error-handling.ts - 错误处理示例
- 04-advanced-features.ts - 高级特性示例
- index.ts - 综合示例
运行示例:
# 运行综合示例
npm run start:example
# 运行特定示例
npm run start:example -- examples/01-basic-usage.ts🎯 设计理念
本库遵循以下设计理念:
- 专注核心功能 - 只做请求和响应处理,不包含缓存、自动重试等高级功能
- 类型安全优先 - 提供完整的 TypeScript 类型支持
- 简洁易用 - API 设计简洁直观,学习成本低
- 灵活扩展 - 通过 Hooks 和实例扩展机制支持定制化需求
对于缓存、自动请求、请求去重等高级功能,建议使用上层框架如 TanStack Query 来实现。
🔧 开发
# 安装依赖
pnpm install
# 开发模式
pnpm dev
# 运行测试
pnpm test
# 类型检查
pnpm typecheck
# 代码检查
pnpm lint
# 构建
pnpm build🧪 测试
本项目使用 Vitest 进行单元测试。
测试 API 文档:Apifox Mock API
🤝 贡献
欢迎提交 Issue 和 Pull Request!
