hook-fetch 3.0.0-beta.0 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +263 -0
- package/README.en.md +28 -20
- package/README.md +40 -28
- package/dist/cjs/base.cjs +5 -0
- package/dist/cjs/index.cjs +1 -4
- package/dist/cjs/plugins/index.cjs +2 -1
- package/dist/cjs/react/index.cjs +1 -1
- package/dist/cjs/sse.cjs +2 -2
- package/dist/cjs/vue/index.cjs +1 -1
- package/dist/es/base.mjs +5 -0
- package/dist/es/index.mjs +1 -4
- package/dist/es/plugins/index.mjs +2 -1
- package/dist/es/react/index.mjs +1 -1
- package/dist/es/sse.mjs +2 -2
- package/dist/es/vue/index.mjs +1 -1
- package/dist/umd/index.js +4 -4
- package/package.json +12 -6
- package/types/index-DYCLL3nB.d.ts +110 -0
- package/types/index.d.ts +3 -3
- package/types/plugins/index.d.ts +24 -3
- package/types/plugins/sse.d.ts +2 -2
- package/types/react/index.d.ts +6 -6
- package/types/{sse-DPRkQwhR.d.ts → sse-DOsoKbYA.d.ts} +3 -3
- package/types/types-Cwp1SGHA.d.ts +150 -0
- package/types/vue/index.d.ts +5 -5
- package/types/index-CYxVuurN.d.ts +0 -108
- package/types/types-CAGBd7wv.d.ts +0 -110
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# hook-fetch
|
|
2
|
+
|
|
3
|
+
## 3.0.0-beta.1
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- ## v3.0.0 - Context-Based Plugin API
|
|
8
|
+
|
|
9
|
+
### 💥 Breaking Changes
|
|
10
|
+
- **插件 API 全面重构**:所有插件钩子从直接参数改为统一的 Context 对象模式
|
|
11
|
+
- `beforeRequest(ctx)` - 接收 `{ config, resolve, reject }`
|
|
12
|
+
- `afterResponse(ctx)` - 接收 `{ config, response, resolve, reject }`
|
|
13
|
+
- `onError(ctx)` - 接收 `{ error, config, resolve, reject }`
|
|
14
|
+
- `onFinally(ctx)` - 接收 `{ config }`
|
|
15
|
+
- **Pipeline Decision 机制**:插件可通过 `resolve()` 短路返回数据或 `reject()` 提前中止请求
|
|
16
|
+
- **插件优先级系统**:通过 `priority` 字段控制插件执行顺序(升序,默认 0)
|
|
17
|
+
|
|
18
|
+
### ✨ 新功能
|
|
19
|
+
- **Retry 插件** (`retryPlugin`):支持指数退避、线性退避、自定义退避策略,可配置重试条件和最大重试次数
|
|
20
|
+
- **完整流式处理**:新增 `beforeStream`、`transformStreamChunk`、`afterStream` 生命周期钩子
|
|
21
|
+
- **onError 错误恢复**:`onError` 钩子中可调用 `resolve()` 返回降级数据或重试结果(如 401 Token 刷新 → 重试)
|
|
22
|
+
- **增强的泛型支持**:`HookFetchPlugin<T, E>`、`OnErrorContext<T, E, S>` 等全面支持状态泛型
|
|
23
|
+
|
|
24
|
+
### 🔧 改进
|
|
25
|
+
- **架构重组**:新增 `decision.ts`(Pipeline 决策)、`pipeline.ts`(插件管道)、`request.ts`(请求生命周期)、`executor.ts`(HTTP 执行器)
|
|
26
|
+
- **PluginManager**:插件去重(同名插件取最后注册的)、优先级排序
|
|
27
|
+
- **ResponseError 增强**:携带完整请求配置上下文,支持泛型错误类型
|
|
28
|
+
- **SSE 插件改进**:集成 `transformStreamChunk` 钩子,支持自定义分隔符和 JSON 解析配置
|
|
29
|
+
|
|
30
|
+
## 2.3.1
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- 修改resolve后仍然会继续请求的问题
|
|
35
|
+
|
|
36
|
+
## 2.3.0
|
|
37
|
+
|
|
38
|
+
### Minor Changes
|
|
39
|
+
|
|
40
|
+
- 发布 2.3,主要变化:
|
|
41
|
+
- 新增 BodyType 并应用到请求/插件泛型,支持 string/FormData/Blob/ArrayBuffer/ReadableStream 等原生 body 直传。
|
|
42
|
+
- 优化 upload:支持对象或 FormData 自动转换为 FormData,上传数据类型推导更准确。
|
|
43
|
+
- Content-Type 为 text/plain 时保持原始字符串 body,纯文本接口按预期提交。
|
|
44
|
+
- 补充本地文件上传与 text/plain 测试用例,覆盖多文件、请求头透传与流式上传中断场景。
|
|
45
|
+
|
|
46
|
+
## 2.2.4
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- Improve type safety for streaming API:
|
|
51
|
+
- Add generic parameter support to `stream<U = T>()` method, allowing type override at stream stage
|
|
52
|
+
- Improve TypeScript inference: recommend specifying response type at request method level (e.g., `post<T>()`) rather than stream level for better type safety
|
|
53
|
+
- Update internal type handling in stream implementation for more accurate type narrowing
|
|
54
|
+
|
|
55
|
+
## 2.2.3
|
|
56
|
+
|
|
57
|
+
### Patch Changes
|
|
58
|
+
|
|
59
|
+
- 新增请求去重插件并改进错误处理
|
|
60
|
+
|
|
61
|
+
## 新增功能
|
|
62
|
+
- **请求去重插件 (dedupePlugin)**: 新增 `dedupePlugin` 用于防止并发的相同请求。插件会根据 URL、HTTP 方法、参数和请求体数据生成唯一标识,当检测到相同标识的请求正在进行时,后续请求会抛出 `DedupeError`
|
|
63
|
+
- 提供 `isDedupeError` 辅助函数用于判断错误类型
|
|
64
|
+
- 支持通过 `extra.dedupeAble` 选项禁用特定请求的去重功能
|
|
65
|
+
- ⚠️ 官方不推荐在生产环境中使用,建议通过应用层设计(如禁用按钮、防抖节流、状态管理)来避免重复请求
|
|
66
|
+
|
|
67
|
+
## 改进
|
|
68
|
+
- **类型定义完善**: 在 `RequestConfig`、`BaseRequestOptions` 和 `OptionProps` 中添加 `extra` 字段支持,允许传递额外的请求配置
|
|
69
|
+
- **错误处理优化**: 改进 React 和 Vue hooks 的错误处理逻辑,过滤 `AbortError` 和 JSON 解析错误,避免触发不必要的错误回调
|
|
70
|
+
|
|
71
|
+
## 文档更新
|
|
72
|
+
- 添加请求去重插件的完整文档和使用示例
|
|
73
|
+
- 更新中英文文档
|
|
74
|
+
|
|
75
|
+
## 2.2.2
|
|
76
|
+
|
|
77
|
+
### Patch Changes
|
|
78
|
+
|
|
79
|
+
- 1. 修复 vue 和 react 的 hooks 状态管理异常 bug
|
|
80
|
+
2. 允许使用的时候临时传入插件
|
|
81
|
+
|
|
82
|
+
## 2.2.1
|
|
83
|
+
|
|
84
|
+
### Patch Changes
|
|
85
|
+
|
|
86
|
+
- 修改beforeRequest逻辑, 使其支持中断请求直接返回值
|
|
87
|
+
|
|
88
|
+
**_主要用途:_**
|
|
89
|
+
- 缓存请求
|
|
90
|
+
|
|
91
|
+
example:[cache.test.ts](https://github.com/JsonLee12138/hook-fetch/blob/main/packages/core/__test__/cache.test.ts)
|
|
92
|
+
|
|
93
|
+
## 2.2.0
|
|
94
|
+
|
|
95
|
+
### Minor Changes
|
|
96
|
+
|
|
97
|
+
- ### Major Changes
|
|
98
|
+
- ### 💥 Breaking Changes
|
|
99
|
+
- 移除旧有的 `qsArrayFormat` 配置字段,现改为通过 `qsConfig` 提供完整的 `qs.stringify` 选项;依赖该字段的代码需迁移到新 API。
|
|
100
|
+
|
|
101
|
+
### 更新内容
|
|
102
|
+
- 新增 `qsConfig` 全局配置,允许在 `hookFetch` create 阶段自定义传给 `qs.stringify` 的参数,默认仍为 `arrayFormat: 'repeat'`。
|
|
103
|
+
- 各类请求方法接收 `RequestOptions.qsConfig`,可在单次调用时覆盖全局设置,影响 URL 拼接与 `application/x-www-form-urlencoded` 体序列化。
|
|
104
|
+
|
|
105
|
+
## 2.1.6
|
|
106
|
+
|
|
107
|
+
### Patch Changes
|
|
108
|
+
|
|
109
|
+
- 修复错误异常问题
|
|
110
|
+
|
|
111
|
+
## 2.1.5
|
|
112
|
+
|
|
113
|
+
### Patch Changes
|
|
114
|
+
|
|
115
|
+
- 更新文档
|
|
116
|
+
|
|
117
|
+
## 2.1.4
|
|
118
|
+
|
|
119
|
+
### Patch Changes
|
|
120
|
+
|
|
121
|
+
- 修复beforeRequest中不能抛错的问题
|
|
122
|
+
|
|
123
|
+
## 2.1.3
|
|
124
|
+
|
|
125
|
+
### Patch Changes
|
|
126
|
+
|
|
127
|
+
- 修复stream方法的错误不会走plugin的错误生命周期的bug
|
|
128
|
+
|
|
129
|
+
## 2.1.2
|
|
130
|
+
|
|
131
|
+
### Patch Changes
|
|
132
|
+
|
|
133
|
+
- 修复抛出的HookFetchRequest类型不支持泛型的问题
|
|
134
|
+
|
|
135
|
+
## 2.1.1
|
|
136
|
+
|
|
137
|
+
### Patch Changes
|
|
138
|
+
|
|
139
|
+
- 8d4d6b6: 修复HookFetchRequest实例没有抛出的问题
|
|
140
|
+
|
|
141
|
+
## 2.1.1-beta.0
|
|
142
|
+
|
|
143
|
+
### Patch Changes
|
|
144
|
+
|
|
145
|
+
- 修复HookFetchRequest实例没有抛出的问题
|
|
146
|
+
|
|
147
|
+
## 3.0.0-beta.0
|
|
148
|
+
|
|
149
|
+
### Major Changes
|
|
150
|
+
|
|
151
|
+
- 4b15105: 修改changeset配置, 改用changeset进行发布
|
|
152
|
+
|
|
153
|
+
## v2.1.0 💥
|
|
154
|
+
|
|
155
|
+
**发布日期**: 2025-08-08
|
|
156
|
+
|
|
157
|
+
#### 💔 破坏性变更
|
|
158
|
+
|
|
159
|
+
- 泛型签名调整:`HookFetch` 与 `hookFetch.create` 的泛型从
|
|
160
|
+
`<R extends AnyObject = AnyObject, K extends keyof R = 'data', E = AnyObject>`
|
|
161
|
+
调整为
|
|
162
|
+
`<R extends AnyObject | null = null, K extends keyof R = never, E = AnyObject>`。
|
|
163
|
+
- 当 `R = null`(默认)时:`json<T>()` 的返回类型为 `T`,不做包裹映射(更贴近原生 fetch 的直觉)。
|
|
164
|
+
- 当你需要“包裹响应”并做键映射时:显式传入响应包裹类型和键名,例如 `hookFetch.create<ResponseVO, 'data'>(...)`,此时 `json<User>()` 的返回类型为 `ResponseVO` 且其中 `data` 为 `User`。
|
|
165
|
+
|
|
166
|
+
#### 🔧 迁移指南
|
|
167
|
+
|
|
168
|
+
- 旧代码:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
interface ResponseVO {
|
|
172
|
+
code: number;
|
|
173
|
+
message: string;
|
|
174
|
+
data: never;
|
|
175
|
+
}
|
|
176
|
+
const api = hookFetch.create<ResponseVO>({ baseURL: "..." });
|
|
177
|
+
const res = await api.get<User>("/user").json();
|
|
178
|
+
// res.data: User
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
新代码需显式指定键名:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const api = hookFetch.create<ResponseVO, "data">({ baseURL: "..." });
|
|
185
|
+
const res = await api.get<User>("/user").json();
|
|
186
|
+
// res.data: User
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
- 若无需包裹(直接拿到 `T`):
|
|
190
|
+
```ts
|
|
191
|
+
const api = hookFetch.create(); // 等价于 <null, never>
|
|
192
|
+
const user = await api.get<User>("/user").json(); // user: User
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### 🧰 其他
|
|
196
|
+
|
|
197
|
+
- 同步更新文档:README 与 API 参考已更新示例,明确 `R | null` 与 `K` 的用法。
|
|
198
|
+
|
|
199
|
+
### v2.0.7 🛠️
|
|
200
|
+
|
|
201
|
+
**发布日期**: 2025-08-08
|
|
202
|
+
|
|
203
|
+
#### 🐛 修复
|
|
204
|
+
|
|
205
|
+
- 修复 `json`、`text`、`blob`、`arrayBuffer`、`formData`、`bytes` 方法的类型推断缺失问题(更完善的返回值类型提示)。
|
|
206
|
+
|
|
207
|
+
#### 🧱 基础设施
|
|
208
|
+
|
|
209
|
+
- 调整与修复发布 CI/CD 流程相关配置。
|
|
210
|
+
|
|
211
|
+
### v2.0.6
|
|
212
|
+
|
|
213
|
+
**发布日期**: 2025-08-07
|
|
214
|
+
|
|
215
|
+
#### 🔧 变更
|
|
216
|
+
|
|
217
|
+
- 发布流程与版本稳定性相关的调整。
|
|
218
|
+
|
|
219
|
+
### v2.0.3 🎉
|
|
220
|
+
|
|
221
|
+
**发布日期**: 2025-06-30
|
|
222
|
+
|
|
223
|
+
#### 💔 破坏性变更
|
|
224
|
+
|
|
225
|
+
- **移除默认JSON解析**: 不再自动解析JSON响应,需要显式调用 `.json()` 方法
|
|
226
|
+
- **更明确的响应处理**: 提供更明确的响应数据处理方式,避免隐式行为
|
|
227
|
+
|
|
228
|
+
#### 🔧 API 调整
|
|
229
|
+
|
|
230
|
+
- 所有请求方法现在需要显式调用响应处理方法(如 `.json()`, `.text()` 等)
|
|
231
|
+
- 提高了API的明确性和可预测性
|
|
232
|
+
|
|
233
|
+
#### 📚 文档更新
|
|
234
|
+
|
|
235
|
+
- 更新了所有示例代码,明确显示 `.json()` 调用
|
|
236
|
+
- 改进了响应处理的文档说明
|
|
237
|
+
|
|
238
|
+
### v1.0.x
|
|
239
|
+
|
|
240
|
+
**发布日期**: 2025-04
|
|
241
|
+
|
|
242
|
+
#### 🎯 首次发布
|
|
243
|
+
|
|
244
|
+
- 基于原生 fetch API 的现代化 HTTP 请求库
|
|
245
|
+
- **自动JSON解析**: 默认自动解析JSON响应
|
|
246
|
+
- **完整插件系统**: 支持 `beforeRequest`, `afterResponse`, `beforeStream`, `transformStreamChunk`, `onError`, `onFinally` 生命周期钩子
|
|
247
|
+
- **Vue Hooks 支持**: 提供 `useHookFetch` Vue 组合式 API
|
|
248
|
+
- **React Hooks 支持**: 提供 `useHookFetch` React Hook
|
|
249
|
+
- **多种响应处理**: 支持 `json()`, `text()`, `blob()`, `arrayBuffer()`, `formData()`, `bytes()` 方法
|
|
250
|
+
- **请求重试机制**: 支持 `.retry()` 方法重试已中断的请求
|
|
251
|
+
- **流式数据处理**: 强大的流式响应处理能力
|
|
252
|
+
- **请求中断**: 支持 `.abort()` 方法中断请求
|
|
253
|
+
- **插件优先级**: 支持插件优先级设置
|
|
254
|
+
- **SSE 支持**: 提供 `sseTextDecoderPlugin` 插件
|
|
255
|
+
- **完整 TypeScript 支持**: 提供完善的类型定义和泛型支持
|
|
256
|
+
- **灵活配置**: 支持超时、baseURL、请求头、参数序列化等配置选项
|
|
257
|
+
- **VSCode 智能提示**: 提供专门的类型声明文件
|
|
258
|
+
|
|
259
|
+
### 即将发布
|
|
260
|
+
|
|
261
|
+
- 更多内置插件
|
|
262
|
+
- 更丰富的插件生态
|
|
263
|
+
- 更多框架集成支持
|
package/README.en.md
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://jsonlee12138.github.io/hook-fetch/"><img src="https://jsonlee12138.github.io/hook-fetch/img/logo.png" /></a><br>
|
|
3
|
+
</div>
|
|
4
|
+
<h1 align="center" style="margin-bottom: 0;">Hook-Fetch</h1>
|
|
5
|
+
<div align="center">
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
[](https://github.com/JsonLee12138/hook-fetch/actions/workflows/release.yml) [](https://packagephobia.com/result?p=hook-fetch) [](https://bundlephobia.com/package/hook-fetch@latest) [](https://npm-stat.com/charts.html?package=hook-fetch) [](https://discord.com/invite/666U6JTCQY)
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
**[DeepWiki](https://deepwiki.com/JsonLee12138/hook-fetch)** **·** **[中文文档](https://github.com/JsonLee12138/hook-fetch/blob/main/README.md)**
|
|
6
10
|
|
|
7
11
|
Hook-Fetch is a powerful request library based on the native fetch API, offering a simpler syntax, richer features, and a more flexible plugin system. It supports request retries, streaming data processing, request cancellation, and more. With its Promise-based chaining style, API requests become simpler and more controllable.
|
|
8
12
|
|
|
13
|
+
</div>
|
|
14
|
+
<br />
|
|
15
|
+
|
|
9
16
|
## Installation
|
|
10
17
|
|
|
11
18
|
```bash
|
|
@@ -149,7 +156,7 @@ Hook-Fetch offers a robust plugin system allowing intervention at various stages
|
|
|
149
156
|
```typescript
|
|
150
157
|
// Custom plugin example: SSE text decoding plugin
|
|
151
158
|
// This is just an example. It's recommended to use the provided `sseTextDecoderPlugin` which has more comprehensive handling
|
|
152
|
-
|
|
159
|
+
function ssePlugin() {
|
|
153
160
|
const decoder = new TextDecoder('utf-8');
|
|
154
161
|
return {
|
|
155
162
|
name: 'sse',
|
|
@@ -159,8 +166,8 @@ const ssePlugin = () => {
|
|
|
159
166
|
}
|
|
160
167
|
return chunk;
|
|
161
168
|
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
164
171
|
|
|
165
172
|
// Register the plugin
|
|
166
173
|
api.use(ssePlugin());
|
|
@@ -176,7 +183,7 @@ for await (const chunk of req.stream<string>()) {
|
|
|
176
183
|
|
|
177
184
|
```typescript
|
|
178
185
|
// Complete plugin example showing the usage of each lifecycle hook
|
|
179
|
-
|
|
186
|
+
function examplePlugin() {
|
|
180
187
|
return {
|
|
181
188
|
name: 'example',
|
|
182
189
|
priority: 1, // Priority, lower numbers have higher priority
|
|
@@ -194,17 +201,18 @@ const examplePlugin = () => {
|
|
|
194
201
|
// Can process response data. context.result is the result after being processed by methods like json()
|
|
195
202
|
if (context.responseType === 'json') {
|
|
196
203
|
// For example, determine if the request is truly successful based on the backend's business code
|
|
197
|
-
if(context.result.code === 200){
|
|
204
|
+
if (context.result.code === 200) {
|
|
198
205
|
// Business success, return context directly
|
|
199
|
-
return context
|
|
200
|
-
}
|
|
206
|
+
return context;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
201
209
|
// Business failure, actively throw a ResponseError, which will be caught in the onError hook
|
|
202
210
|
throw new ResponseError({
|
|
203
211
|
message: context.result.message, // Use the error message from the backend
|
|
204
|
-
status: context.result.code,
|
|
205
|
-
response: context.response,
|
|
212
|
+
status: context.result.code, // Use the business code as the status
|
|
213
|
+
response: context.response, // Original Response object
|
|
206
214
|
config: context.config,
|
|
207
|
-
name: 'BusinessError'
|
|
215
|
+
name: 'BusinessError' // Custom error name
|
|
208
216
|
});
|
|
209
217
|
}
|
|
210
218
|
}
|
|
@@ -233,7 +241,8 @@ const examplePlugin = () => {
|
|
|
233
241
|
if (error.name === 'BusinessError') {
|
|
234
242
|
// Handle custom business errors
|
|
235
243
|
console.error(`Business Error: ${error.message}`);
|
|
236
|
-
}
|
|
244
|
+
}
|
|
245
|
+
else if (error.status === 401) {
|
|
237
246
|
// Handle unauthorized error
|
|
238
247
|
console.error('Login has expired, please log in again');
|
|
239
248
|
// window.location.href = '/login';
|
|
@@ -248,7 +257,7 @@ const examplePlugin = () => {
|
|
|
248
257
|
console.log(`Request to ${config.url} completed`);
|
|
249
258
|
}
|
|
250
259
|
};
|
|
251
|
-
}
|
|
260
|
+
}
|
|
252
261
|
```
|
|
253
262
|
|
|
254
263
|
All lifecycle hooks support both synchronous and asynchronous operations. They can return either a Promise or a direct value. Each hook function receives the current configuration object (config), which can be used to make decisions and handle different request scenarios.
|
|
@@ -355,17 +364,13 @@ interface HookFetchPlugin<T = unknown, E = unknown, P = unknown, D = unknown> {
|
|
|
355
364
|
}
|
|
356
365
|
```
|
|
357
366
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
367
|
## Vue Hooks
|
|
363
368
|
|
|
364
369
|
Hook-Fetch provides Vue Composition API support, making it easier to use in Vue components:
|
|
365
370
|
|
|
366
371
|
```typescript
|
|
367
|
-
import { useHookFetch } from 'hook-fetch/vue';
|
|
368
372
|
import hookFetch from 'hook-fetch';
|
|
373
|
+
import { useHookFetch } from 'hook-fetch/vue';
|
|
369
374
|
|
|
370
375
|
// Create request instance
|
|
371
376
|
const api = hookFetch.create({
|
|
@@ -478,6 +483,7 @@ const YourComponent = () => {
|
|
|
478
483
|
```
|
|
479
484
|
|
|
480
485
|
### vscode hint plugin reference path
|
|
486
|
+
|
|
481
487
|
```typescript
|
|
482
488
|
// Create a file hook-fetch.d.ts in src with the following content
|
|
483
489
|
/// <reference types="hook-fetch/plugins" />
|
|
@@ -493,10 +499,12 @@ const YourComponent = () => {
|
|
|
493
499
|
4. Plugins execute in order of priority.
|
|
494
500
|
|
|
495
501
|
## Upcoming Features
|
|
502
|
+
|
|
496
503
|
- `umd` support
|
|
497
504
|
- More plugin support
|
|
498
505
|
|
|
499
506
|
## 📝 Contribution Guide
|
|
507
|
+
|
|
500
508
|
Feel free to submit `issues` or `pull requests` to help improve `Hook-Fetch`.
|
|
501
509
|
|
|
502
510
|
## 📄 License
|
package/README.md
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://jsonlee12138.github.io/hook-fetch/"><img src="https://jsonlee12138.github.io/hook-fetch/img/logo.png" /></a><br>
|
|
3
|
+
</div>
|
|
4
|
+
<h1 align="center" style="margin-bottom: 0;">Hook-Fetch</h1>
|
|
5
|
+
<div align="center">
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
[](https://github.com/JsonLee12138/hook-fetch/actions/workflows/release.yml) [](https://packagephobia.com/result?p=hook-fetch) [](https://bundlephobia.com/package/hook-fetch@latest) [](https://npm-stat.com/charts.html?package=hook-fetch) [](https://discord.com/invite/666U6JTCQY)
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
**[DeepWiki](https://deepwiki.com/JsonLee12138/hook-fetch)** **·** **[English document](https://github.com/JsonLee12138/hook-fetch/blob/main/README.en.md)**
|
|
6
10
|
|
|
7
11
|
Hook-Fetch 是一个强大的基于原生 fetch API 的请求库,提供了更简洁的语法、更丰富的功能和更灵活的插件系统。它支持请求重试、流式数据处理、中断请求等特性,并且采用Promise链式调用风格,使API请求变得更加简单和可控。
|
|
8
12
|
|
|
13
|
+
</div>
|
|
14
|
+
<br />
|
|
15
|
+
|
|
9
16
|
## 安装
|
|
10
17
|
|
|
11
18
|
```bash
|
|
@@ -149,7 +156,7 @@ Hook-Fetch 提供了强大的插件系统,可以在请求生命周期的各个
|
|
|
149
156
|
```typescript
|
|
150
157
|
// 自定义插件示例:SSE文本解码插件
|
|
151
158
|
// 当前只是示例, 建议使用当前库提供的`sseTextDecoderPlugin`插件, 那里做了更完善的处理
|
|
152
|
-
|
|
159
|
+
function ssePlugin() {
|
|
153
160
|
const decoder = new TextDecoder('utf-8');
|
|
154
161
|
return {
|
|
155
162
|
name: 'sse',
|
|
@@ -159,8 +166,8 @@ const ssePlugin = () => {
|
|
|
159
166
|
}
|
|
160
167
|
return chunk;
|
|
161
168
|
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
164
171
|
|
|
165
172
|
// 注册插件
|
|
166
173
|
api.use(ssePlugin());
|
|
@@ -176,7 +183,7 @@ for await (const chunk of req.stream<string>()) {
|
|
|
176
183
|
|
|
177
184
|
```typescript
|
|
178
185
|
// 完整的插件示例,展示各个生命周期的使用
|
|
179
|
-
|
|
186
|
+
function examplePlugin() {
|
|
180
187
|
return {
|
|
181
188
|
name: 'example',
|
|
182
189
|
priority: 1, // 优先级,数字越小优先级越高
|
|
@@ -194,17 +201,18 @@ const examplePlugin = () => {
|
|
|
194
201
|
// 可以处理响应数据, context.result 是已经过 json() 等方法处理后的结果
|
|
195
202
|
if (context.responseType === 'json') {
|
|
196
203
|
// 例如,根据后端的业务码判断请求是否真正成功
|
|
197
|
-
if(context.result.code === 200){
|
|
204
|
+
if (context.result.code === 200) {
|
|
198
205
|
// 业务成功,直接返回 context
|
|
199
|
-
return context
|
|
200
|
-
}
|
|
206
|
+
return context;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
201
209
|
// 业务失败,主动抛出一个 ResponseError,它将在 onError 钩子中被捕获
|
|
202
210
|
throw new ResponseError({
|
|
203
211
|
message: context.result.message, // 使用后端的错误信息
|
|
204
|
-
status: context.result.code,
|
|
205
|
-
response: context.response,
|
|
212
|
+
status: context.result.code, // 使用后端的业务码作为状态
|
|
213
|
+
response: context.response, // 原始 Response 对象
|
|
206
214
|
config: context.config,
|
|
207
|
-
name: 'BusinessError'
|
|
215
|
+
name: 'BusinessError' // 自定义错误名称
|
|
208
216
|
});
|
|
209
217
|
}
|
|
210
218
|
}
|
|
@@ -233,7 +241,8 @@ const examplePlugin = () => {
|
|
|
233
241
|
if (error.name === 'BusinessError') {
|
|
234
242
|
// 处理自定义的业务错误
|
|
235
243
|
console.error(`业务错误: ${error.message}`);
|
|
236
|
-
}
|
|
244
|
+
}
|
|
245
|
+
else if (error.status === 401) {
|
|
237
246
|
// 处理未授权错误
|
|
238
247
|
console.error('登录已过期,请重新登录');
|
|
239
248
|
// window.location.href = '/login';
|
|
@@ -248,14 +257,14 @@ const examplePlugin = () => {
|
|
|
248
257
|
console.log(`Request to ${config.url} completed`);
|
|
249
258
|
}
|
|
250
259
|
};
|
|
251
|
-
}
|
|
260
|
+
}
|
|
252
261
|
```
|
|
253
262
|
|
|
254
263
|
#### 业务场景封装示例
|
|
255
264
|
|
|
256
265
|
```typescript
|
|
257
266
|
// 创建一个业务请求实例
|
|
258
|
-
|
|
267
|
+
function createRequest() {
|
|
259
268
|
// 创建基础实例
|
|
260
269
|
const request = hookFetch.create({
|
|
261
270
|
baseURL: 'https://api.example.com',
|
|
@@ -322,24 +331,24 @@ const createRequest = () => {
|
|
|
322
331
|
return {
|
|
323
332
|
// 用户相关接口
|
|
324
333
|
user: {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
334
|
+
// 获取用户信息
|
|
335
|
+
getInfo: () => request.get('/user/info').json(),
|
|
336
|
+
// 更新用户信息
|
|
337
|
+
updateInfo: data => request.put('/user/info', data).json(),
|
|
338
|
+
// 修改密码
|
|
339
|
+
changePassword: data => request.post('/user/password', data).json()
|
|
331
340
|
},
|
|
332
341
|
// 订单相关接口
|
|
333
342
|
order: {
|
|
334
343
|
// 获取订单列表
|
|
335
|
-
getList:
|
|
344
|
+
getList: params => request.get('/orders', params).json(),
|
|
336
345
|
// 创建订单
|
|
337
|
-
create:
|
|
346
|
+
create: data => request.post('/orders', data).json(),
|
|
338
347
|
// 取消订单
|
|
339
|
-
cancel:
|
|
348
|
+
cancel: id => request.post(`/orders/${id}/cancel`).json()
|
|
340
349
|
}
|
|
341
350
|
};
|
|
342
|
-
}
|
|
351
|
+
}
|
|
343
352
|
|
|
344
353
|
// 使用示例
|
|
345
354
|
const api = createRequest();
|
|
@@ -355,6 +364,7 @@ const order = await api.order.create({
|
|
|
355
364
|
```
|
|
356
365
|
|
|
357
366
|
插件钩子函数:
|
|
367
|
+
|
|
358
368
|
- `beforeRequest`: 请求发送前处理配置,可以返回新的配置或直接修改配置
|
|
359
369
|
- `afterResponse`: 响应接收后处理数据,可以返回新的响应或直接修改响应
|
|
360
370
|
- `beforeStream`: 流式请求开始时的处理,用于初始化或转换流
|
|
@@ -466,14 +476,13 @@ interface HookFetchPlugin<T = unknown, E = unknown, P = unknown, D = unknown> {
|
|
|
466
476
|
}
|
|
467
477
|
```
|
|
468
478
|
|
|
469
|
-
|
|
470
479
|
## Vue Hooks
|
|
471
480
|
|
|
472
481
|
Hook-Fetch 提供了 Vue 组合式 API 的支持,可以更方便地在 Vue 组件中使用:
|
|
473
482
|
|
|
474
483
|
```typescript
|
|
475
|
-
import { useHookFetch } from 'hook-fetch/vue';
|
|
476
484
|
import hookFetch from 'hook-fetch';
|
|
485
|
+
import { useHookFetch } from 'hook-fetch/vue';
|
|
477
486
|
|
|
478
487
|
// 创建请求实例
|
|
479
488
|
const api = hookFetch.create({
|
|
@@ -586,6 +595,7 @@ const YourComponent = () => {
|
|
|
586
595
|
```
|
|
587
596
|
|
|
588
597
|
### vscode提示插件的引用路径
|
|
598
|
+
|
|
589
599
|
```typescript
|
|
590
600
|
// 在 src 中创建文件 hook-fetch.d.ts, 内容如下
|
|
591
601
|
/// <reference types="hook-fetch/plugins" />
|
|
@@ -601,10 +611,12 @@ const YourComponent = () => {
|
|
|
601
611
|
4. 插件按照优先级顺序执行
|
|
602
612
|
|
|
603
613
|
## 预计开发内容
|
|
614
|
+
|
|
604
615
|
- `umd` 支持
|
|
605
616
|
- 更多的插件支持
|
|
606
617
|
|
|
607
618
|
## 📝 贡献指南
|
|
619
|
+
|
|
608
620
|
欢迎提交`issue`或`pull request`,共同完善`Hook-Fetch`。
|
|
609
621
|
|
|
610
622
|
## 📄 许可证
|