Wretch 开源项目使用教程:现代化 Fetch 封装库的完整指南
前言:为什么需要 Wretch?
在现代 Web 开发中,fetch API 已经成为浏览器原生网络请求的标准。然而,原生 fetch 在使用过程中存在一些痛点:
- ❌ 需要手动处理响应解析(
.json(),.text()) - ❌ HTTP 错误状态码不会自动抛出异常
- ❌ JSON 序列化需要手动设置 headers 和 body
- ❌ 缺乏请求重试、缓存等高级功能
- ❌ 配置重复代码较多
Wretch 正是为了解决这些问题而生的轻量级封装库,它提供了直观的链式 API 和丰富的功能扩展。
Wretch 核心特性一览
| 特性 | 描述 | 优势 |
|---|---|---|
| 🪶 轻量级 | 核心仅 2KB gzip | 几乎无性能开销 |
| 💡 直观语法 | 链式调用设计 | 代码更易读易写 |
| 🧊 不可变设计 | 每次调用返回新实例 | 安全的重用机制 |
| 🔌 模块化扩展 | 插件和中间件系统 | 按需加载功能 |
| 🧩 多平台支持 | 浏览器、Node.js、Deno | 一致的开发体验 |
| 🦺 TypeScript | 完整的类型定义 | 开发时类型安全 |
快速开始
安装 Wretch
# 使用 npm
npm install wretch
# 使用 yarn
yarn add wretch
# 使用 pnpm
pnpm add wretch
基础使用示例
import wretch from 'wretch'
// 最简单的 GET 请求
wretch('https://api.example.com/data')
.get()
.json(data => {
console.log('获取到的数据:', data)
})
.catch(error => {
console.error('请求失败:', error)
})
// 带错误处理的 POST 请求
wretch('https://api.example.com/users')
.post({ name: '张三', age: 25 })
.json(response => {
console.log('用户创建成功:', response)
})
.badRequest(error => {
console.error('请求参数错误:', error)
})
.unauthorized(error => {
console.error('未授权访问:', error)
})
核心功能详解
1. 请求链式操作
Wretch 采用清晰的链式调用设计:
2. 自动错误处理
与传统 fetch 对比:
// 原生 fetch 的错误处理
fetch('/api/data')
.then(response => {
if (!response.ok) {
if (response.status === 404) throw new Error('Not found')
else if (response.status === 401) throw new Error('Unauthorized')
// ... 更多状态码判断
}
return response.json()
})
.then(data => console.log(data))
.catch(error => console.error(error))
// Wretch 的错误处理
wretch('/api/data')
.get()
.notFound(error => console.error('404错误'))
.unauthorized(error => console.error('401错误'))
.error(500, error => console.error('服务器错误'))
.json(data => console.log(data))
3. 智能 JSON 处理
Wretch 自动处理 JSON 序列化:
// 自动设置 Content-Type 为 application/json
wretch('/api/users')
.post({ name: '李四', email: 'lisi@example.com' })
.json(response => console.log(response))
// 等价于原生 fetch
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: '李四', email: 'lisi@example.com' })
})
高级功能:Addons 插件系统
QueryString Addon
import QueryStringAddon from 'wretch/addons/queryString'
const api = wretch('https://api.example.com')
.addon(QueryStringAddon)
// 构建查询参数
api.query({ page: 1, limit: 20, sort: 'name' })
.get('/users')
.json(users => console.log(users))
// 输出 URL: https://api.example.com/users?page=1&limit=20&sort=name
FormData Addon
import FormDataAddon from 'wretch/addons/formData'
const formData = {
username: 'john_doe',
avatar: fileInput.files[0], // 文件对象
profile: {
age: 30,
hobbies: ['reading', 'swimming']
}
}
wretch('/api/upload')
.addon(FormDataAddon)
.formData(formData)
.post()
.json(response => console.log('上传成功'))
完整的 Addons 功能对比表
| Addon 名称 | 功能描述 | 使用场景 |
|---|---|---|
QueryString | 查询参数构建 | API 分页、过滤、排序 |
FormData | 多部分表单数据 | 文件上传、复杂表单 |
FormUrl | URL 编码表单 | 传统表单提交 |
Abort | 请求取消 | 超时控制、用户取消 |
BasicAuth | 基础认证 | 简单的 API 认证 |
Progress | 进度监控 | 大文件上传下载 |
Perfs | 性能监控 | 请求性能分析 |
Middlewares 中间件系统
重试中间件 (Retry)
import { retry } from 'wretch/middlewares'
const resilientAPI = wretch('https://api.example.com')
.middlewares([
retry({
delayTimer: 1000, // 初始延迟1秒
delayRamp: (delay, attempts) => delay * attempts, // 指数退避
maxAttempts: 5, // 最多重试5次
until: (response, error) => {
// 只在服务器错误时重试
return response && response.status < 500
},
onRetry: ({ response, url, options }) => {
console.log(`重试请求: ${url}, 尝试次数: ${options.retryCount}`)
}
})
])
// 使用带重试的API
resilientAPI.get('/unstable-endpoint')
.json(data => console.log('最终成功:', data))
去重中间件 (Dedupe)
import { dedupe } from 'wretch/middlewares'
const dedupeAPI = wretch('https://api.example.com')
.middlewares([
dedupe({
// 只对GET请求去重
skip: (url, opts) => opts.method !== 'GET',
// 自定义缓存键
key: (url, opts) => `${opts.method}@${url}@${JSON.stringify(opts.headers)}`
})
])
// 多个相同请求只会实际发送一个
dedupeAPI.get('/data').json(console.log)
dedupeAPI.get('/data').json(console.log) // 使用缓存结果
缓存中间件 (Throttling Cache)
import { throttlingCache } from 'wretch/middlewares'
const cachedAPI = wretch('https://api.example.com')
.middlewares([
throttlingCache({
throttle: 30000, // 缓存30秒
condition: response => response.ok, // 只缓存成功响应
key: (url, opts) => `${opts.method}@${url}`
})
])
// 30秒内的相同请求会返回缓存结果
cachedAPI.get('/user-profile')
.json(profile => console.log('用户配置:', profile))
实战案例:构建完整的 API 客户端
1. 基础 API 客户端
// apiClient.js
import wretch from 'wretch'
import { retry, dedupe } from 'wretch/middlewares'
import QueryStringAddon from 'wretch/addons/queryString'
class APIClient {
constructor(baseURL, options = {}) {
this.client = wretch(baseURL)
.addon(QueryStringAddon)
.middlewares([
retry({ maxAttempts: 3, delayTimer: 1000 }),
dedupe()
])
.errorType('json')
.resolve(r => r.json())
this.options = options
}
// 用户管理
async getUsers(params = {}) {
return this.client
.query(params)
.get('/users')
.catch(error => this.handleError(error, '获取用户列表失败'))
}
async createUser(userData) {
return this.client
.post(userData)
.url('/users')
.catch(error => this.handleError(error, '创建用户失败'))
}
// 错误处理
handleError(error, defaultMessage) {
if (error.json) {
throw new Error(error.json.message || defaultMessage)
}
throw new Error(defaultMessage)
}
}
// 使用示例
const api = new APIClient('https://api.example.com')
// 获取用户列表
const users = await api.getUsers({ page: 1, limit: 20 })
// 创建新用户
const newUser = await api.createUser({
name: '王五',
email: 'wangwu@example.com',
role: 'user'
})
2. 带认证的 API 客户端
// authApiClient.js
import wretch from 'wretch'
import { retry } from 'wretch/middlewares'
import BasicAuthAddon from 'wretch/addons/basicAuth'
class AuthAPIClient {
constructor(baseURL) {
this.baseClient = wretch(baseURL)
.addon(BasicAuthAddon)
.middlewares([retry({ maxAttempts: 2 })])
.errorType('json')
this.token = null
}
setToken(token) {
this.token = token
return this
}
get client() {
let client = this.baseClient
if (this.token) {
client = client.auth(`Bearer ${this.token}`)
}
return client
}
async login(credentials) {
const response = await this.client
.post(credentials)
.url('/auth/login')
.json()
this.setToken(response.token)
return response
}
async getProtectedData() {
return this.client
.get('/protected/data')
.unauthorized(async (error, originalRequest) => {
// Token 过期,尝试刷新
const newToken = await this.refreshToken()
this.setToken(newToken)
// 重试原始请求
return originalRequest.auth(`Bearer ${newToken}`).get().json()
})
.json()
}
async refreshToken() {
// 实现token刷新逻辑
const response = await this.client
.post({ refreshToken: this.refreshToken })
.url('/auth/refresh')
.json()
return response.token
}
}
性能优化最佳实践
1. 请求合并与缓存策略
// 使用去重和缓存中间件
const optimizedAPI = wretch('https://api.example.com')
.middlewares([
dedupe(), // 避免重复请求
throttlingCache({ throttle: 60000 }) // 缓存1分钟
])
// 配置全局默认选项
wretch.options({
mode: 'cors',
credentials: 'include',
cache: 'default'
})
2. 错误处理优化
// 统一的错误处理封装
function createAPIWithErrorHandling(baseURL) {
return wretch(baseURL)
.errorType('json')
.catcher(404, error => {
console.error('资源不存在:', error)
throw new Error('请求的资源不存在')
})
.catcher(500, error => {
console.error('服务器错误:', error)
throw new Error('服务器内部错误,请稍后重试')
})
.catcherFallback(error => {
console.error('未知错误:', error)
throw new Error('网络请求失败')
})
}
常见问题解答 (FAQ)
Q1: Wretch 和 axios 有什么区别?
| 特性 | Wretch | Axios |
|---|---|---|
| 大小 | ~2KB gzip | ~4KB gzip |
| 依赖 | 无依赖 | 需要 http adapter |
| 语法 | 链式调用,更简洁 | 配置对象形式 |
| Tree Shaking | 支持按需导入 | 全部导入 |
| 原生支持 | 基于 fetch API | 基于 XMLHttpRequest |
Q2: 如何在 Node.js 中使用 Wretch?
import wretch from 'wretch'
import fetch from 'node-fetch'
import { FormData } from 'node-fetch'
// 提供必要的 polyfills
wretch.polyfills({
fetch,
FormData
})
// 现在可以正常使用
const data = await wretch('https://api.example.com')
.get()
.json()
Q3: 如何处理文件上传?
import FormDataAddon from 'wretch/addons/formData'
const formData = {
file: fileObject,
metadata: JSON.stringify({ description: '项目文档' })
}
wretch('/api/upload')
.addon(FormDataAddon)
.formData(formData)
.post()
.json(response => console.log('上传成功:', response))
总结
Wretch 作为一个轻量级的 fetch 封装库,提供了现代化、直观的 API 设计,极大地简化了网络请求的处理。通过其模块化的插件系统和中间件机制,开发者可以按需扩展功能,保持代码的简洁性和可维护性。
主要优势:
- ✅ 极小的体积开销
- ✅ 直观的链式调用语法
- ✅ 强大的错误处理机制
- ✅ 丰富的插件生态系统
- ✅ 优秀的 TypeScript 支持
无论是简单的数据获取还是复杂的 API 客户端构建,Wretch 都能提供优雅的解决方案。建议在实际项目中尝试使用,体验其带来的开发效率提升。
下一步学习建议:
- 阅读官方文档深入了解每个 API 的细节
- 尝试编写自定义中间件来解决特定业务需求
- 探索更多的 addons 来扩展 Wretch 的功能
- 在项目中逐步替换现有的请求库,体验改进效果
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



