@net-vert/core 0.3.0 → 0.3.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.
Files changed (2) hide show
  1. package/README.md +42 -444
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -46,482 +46,80 @@ inject(axiosAdapter); // 注入 axios 实例
46
46
  ### 2️⃣ 发起请求
47
47
 
48
48
  ```typescript
49
- const api = useRequestor();
49
+ const requestor = useRequestor();
50
50
 
51
- api.get('/user/info', { params: { id: 1 } }).then(console.log);
52
- api.post('/user/create', { name: 'Alice' }).then(console.log);
51
+ requestor.get('/user/info', { params: { id: 1 } }).then(console.log);
52
+ requestor.post('/user/create', { name: 'Alice' }).then(console.log);
53
53
  ```
54
54
 
55
55
  ---
56
56
 
57
57
  ## 🛠 扩展能力(requestExtender)
58
58
 
59
+ ### 缓存请求器(cacheRequestor)
59
60
  ```typescript
60
- import { requestExtender } from '@net-vert/core';
61
- ```
62
-
63
- **缓存请求**
64
- ```typescript
65
- const cachedApi = requestExtender.cacheRequestor();
66
- cachedApi.get('/user/info', { params: { id: 1 } });
67
- ```
68
-
69
- ✅ **幂等请求**
70
- ```typescript
71
- const idempotentApi = requestExtender.idempotencyRequestor();
72
- idempotentApi.post('/user/create', { name: 'Alice' });
73
- ```
74
-
75
- ✅ **自动重试**
76
- ```typescript
77
- const retryApi = requestExtender.retryRequestor({ retries: 3, delay: 1000 });
78
- retryApi.get('/unstable-api');
79
- ```
80
-
81
- ---
82
-
83
- ## 🔎 缓存设计说明
84
-
85
- - 本库默认内置缓存支持
86
- - 用户无需关注存储机制,专注请求本身
87
-
88
- ---
89
-
90
- ## 🧩 核心 API
91
-
92
- | 方法 | 描述 |
93
- |-----|------|
94
- | `inject(adapter, instanceKey?)` | 注入请求适配器,不填默认为'default' |
95
- | `useRequestor(instanceKey?)` | 获取请求实例 |
96
- | `requestExtender.cacheRequestor(options)` | 创建带缓存能力的请求器 |
97
- | `requestExtender.idempotencyRequestor(options)` | 创建幂等请求器 |
98
- | `requestExtender.retryRequestor(options)` | 创建重试请求器 |
99
-
100
-
101
- ---
102
-
103
- ## 🗂 缓存扩展 `requestExtender.cacheRequestor(options)`
104
-
105
- `cacheRequestor` 是 `@net-vert/core` 内置的智能缓存增强器,提供多维度缓存控制能力,支持同步/异步校验策略,所有cacheRequestor共享一个存储空间。
106
-
107
- ### ✅ 核心特性
108
-
109
- - **🚀 多级缓存策略**
110
- 内存缓存 + 持久化存储(未来由 `@net-vert/cache` 提供)
111
-
112
- - **🔗 智能并发合并**
113
- 相同请求共享 Promise,避免重复网络消耗
114
-
115
- - **⏳ 动态缓存控制**
116
- 支持时间/逻辑双重失效校验机制
117
-
118
- - **🧩 弹性校验策略**
119
- 支持同步/异步缓存有效性检查
120
-
121
- ---
122
-
123
- ### ⚙️ 配置参数
124
-
125
- | 参数 | 类型 | 说明 | 默认值 |
126
- |--------------|--------------------------------------------------------------------|-------------------------------------------------------------|----------------|
127
- | `key` | `(config: UnifiedConfig) => string` | 自定义缓存键生成规则 | `config.url` |
128
- | `persist` | `boolean` | 启用持久化存储(默认内存存储) | `false` |
129
- | `duration` | `number` 或 `({ key, config, response }) => number` | 缓存时间(ms)或动态计算函数 | `Infinity` |
130
- | `isValid` | `({ key, config, cachedData }) => boolean \| Promise<boolean>` | 缓存有效性校验(支持异步校验) | - |
131
-
132
- ---
133
-
134
- ### 📥 基础使用
135
-
136
- ```typescript
137
- import { requestExtender } from '@net-vert/core';
138
-
139
- const api = requestExtender.cacheRequestor({
140
- duration: 3000, // 缓存3秒
141
- key: config => `${config.method}:${config.url}` // 复合键
142
- });
143
-
144
- // 首次请求将缓存
145
- api.get('/user').then(console.log);
146
-
147
- // 3秒内相同请求直接返回缓存
148
- api.get('/user').then(console.log);
149
- ```
150
-
151
- ### 🎯 动态缓存示例
152
-
153
- #### 根据响应数据设置缓存时间
154
- ```typescript
155
- requestExtender.cacheRequestor({
156
- duration: ({ response }) => response.data.isHot ? 10000 : 3000
157
- });
158
- ```
159
-
160
- #### 权限变更时失效缓存
161
- ```typescript
162
- requestExtender.cacheRequestor({
163
- isValid: ({ cachedData }) => {
164
- return cachedData.value.permission === currentUser.permission
165
- }
166
- });
167
- ```
168
-
169
- #### 异步校验缓存有效性
170
- ```typescript
171
- requestExtender.cacheRequestor({
172
- async isValid({ key }) {
173
- const { valid } = await fetch('/cache/validate', { body: key })
174
- return valid
175
- }
176
- });
177
- ```
178
-
179
- ---
180
-
181
- ### 🛠 工作机制
182
-
183
- ```mermaid
184
- graph TB
185
- A[请求进入] --> B{存在Promise缓存?}
186
- B -->|是| C[共享请求]
187
- B -->|否| D{存在物理缓存?}
188
- D -->|是| E[执行isValid校验]
189
- E -->|有效| F[返回缓存]
190
- E -->|无效| G[清理缓存]
191
- D -->|否| H[发起新请求]
192
- H --> I[缓存响应数据]
193
- ```
194
-
195
- ---
196
-
197
- ### ⚠️ 注意事项
198
-
199
- 1. **缓存穿透防护**
200
- 当 `isValid` 返回 `false` 时会主动清理缓存,后续请求将触发新请求
201
-
202
- 2. **异步校验建议**
203
- 耗时较长的异步校验建议配合 `duration` 使用,避免校验期间重复请求
204
-
205
- 3. **内存管理**
206
- 高频数据建议启用 `persist` 持久化存储,防止内存溢出
207
- ```
208
-
209
- ```
210
-
211
- ## ♻️ 幂等扩展 `requestExtender.idempotencyRequestor(options)`
212
-
213
- `idempotencyRequestor` 是基于 `cacheRequestor` 封装的幂等增强器,确保同一参数的请求,在请求未完成前只发送一次,自动合并并发请求,避免重复提交和资源浪费。
214
-
215
- ---
216
-
217
- ### ✅ 核心特性
218
-
219
- - 采用 **哈希生成请求唯一标识**,自动识别重复请求
220
- - 请求未完成时直接复用 Promise,避免短时间内重复请求接口
221
- - 请求完成自动清理,确保后续请求正常发起
222
- - 内存缓存(`persist: false`),适合表单提交、按钮防抖等场景
223
-
224
- ---
225
-
226
- ### ⚙️ 内部默认的哈希算法(hashRequest)
227
-
228
- ```typescript
229
- const hashRequest = (config: UnifiedConfig) => {
230
- const { method, url, params, data } = config
231
- return [method, url, JSON.stringify(params), JSON.stringify(data)].join('|')
61
+ interface CacheConfig {
62
+ key?: (config: UnifiedConfig) => string
63
+ duration?: number | ({ key, config, response }) => number
64
+ persist?: boolean
65
+ sync?: boolean
66
+ isValid?: ({ key, config, cachedData }) => boolean | Promise<boolean>
232
67
  }
233
68
  ```
234
- 支持用户传入自定义生成规则:
69
+ - **key**:缓存键生成函数(默认使用URL+参数哈希)
70
+ - **duration**:缓存时长(ms),支持动态计算过期时间
71
+ - **persist**:是否持久化到indexdeeb, localStorage(同步模式只能存储到localStorage)
72
+ - **sync**:是否启用同步模式
73
+ - **isValid**:缓存有效性校验函数(同步模式只能传入同步校验函数)
235
74
 
75
+ ### 幂等请求器(idempotencyRequestor)
236
76
  ```typescript
237
- const idempotentApi = requestExtender.idempotencyRequestor((config) => {
238
- return `custom-key-${config.url}`;
239
- });
77
+ (genKey?: (config) => string)
240
78
  ```
79
+ - **genKey**:自定义请求唯一标识生成函数(默认使用method+url+参数哈希)
241
80
 
242
- ---
243
-
244
- ## 🔁 重试扩展 `requestExtender.retryRequestor(options)`
245
-
246
- `retryRequestor` 是基于 `Requestor` 增强的请求重试器,提供自动重试机制,确保请求失败时自动重试,提升请求稳定性。
247
-
248
- ---
249
-
250
- ### ✅ 核心特性
251
-
252
- - 支持 **最大重试次数**,可避免无限重试
253
- - 支持 **延迟重试**,延迟时间可自定义,默认 1000ms
254
- - 支持 **重试条件**,根据特定错误判断是否重试
255
- - 自动处理请求失败,符合幂等性原则,保证稳定性
256
-
257
- ---
258
-
259
- ### ⚙️ 配置选项
260
-
261
- | 参数 | 类型 | 说明 | 默认值 |
262
- | ----------------- | ------------------------------------------ | ------------------------------------------------ | ------------ |
263
- | `retries` | `number` | 最大重试次数 | `3` |
264
- | `delay` | `number` 或 `({attempt: number}) => number` | 延迟重试时间(默认延迟 1000ms) | `1000ms` |
265
- | `retryCondition` | `(error: any) => boolean` | 重试条件,返回 `true` 时触发重试(默认对所有错误重试) | `() => true` |
266
-
267
- ---
268
-
269
- ### 📥 使用示例
270
-
271
- ```typescript
272
- import { requestExtender } from '@net-vert/core';
273
-
274
- // 配置最大重试次数为 5 次,延迟 2 秒
275
- const retryApi = requestExtender.retryRequestor({
276
- retries: 5,
277
- delay: 2000
278
- });
279
-
280
- // 请求失败时自动重试
281
- retryApi.get('/unstable-api').then(console.log).catch(console.error);
282
- ```
283
-
284
- ---
285
-
286
- ### 🔎 重试逻辑解析
287
-
288
- 1. **最大重试次数 (`retries`)**:当请求失败时,最多重试 `retries` 次。
289
- 2. **延迟策略 (`delay`)**:每次重试之间等待一段时间,支持固定时间或动态计算。
290
- - 默认:1000ms(1秒)
291
- - 可以根据重试次数动态调整延迟时间:
292
- ```typescript
293
- delay: (attempt) => attempt * 1000 // 每次重试延迟递增
294
- ```
295
- 3. **重试条件 (`retryCondition`)**:只有当错误符合重试条件时才会进行重试,默认为所有错误都重试。
296
-
297
- ---
298
-
299
- ### ⚠️ 使用建议
300
-
301
- - **避免无限重试**:设置合适的最大重试次数(`retries`)和延迟时间(`delay`),防止请求卡死。
302
- - **根据错误类型重试**:可以根据特定的错误类型或者状态码设定 `retryCondition`,例如:
303
- ```typescript
304
- retryCondition: (error) => error.response.status === 500
305
- ```
306
- 这样仅在服务器错误时才会进行重试。
307
-
308
- ---
309
-
310
- ### 🔥 典型应用场景
311
-
312
- - **API 请求失败重试**:对那些偶尔会失败的网络请求,提供自动重试能力,提升成功率。
313
- - **避免因瞬时网络问题而导致的请求失败**。
314
- - **服务宕机恢复后自动重新发起请求**。
315
-
316
- ---
317
-
318
- ### 📥 使用示例
319
-
320
- ```typescript
321
- import { requestExtender } from '@net-vert/core';
322
-
323
- const idempotentApi = requestExtender.idempotencyRequestor();
324
-
325
- // 短时间内连续点击两次,只会发出一次请求
326
- idempotentApi.post('/user/create', { name: 'Alice' }).then(console.log);
327
- idempotentApi.post('/user/create', { name: 'Alice' }).then(console.log);
328
- ```
329
-
330
- 控制台:
331
- ```
332
- ===> 已存在该请求: POST|/user/create|{}|{"name":"Alice"}
333
- ```
334
-
335
- ---
336
-
337
- ### 🔎 典型应用场景
338
-
339
- ✅ 表单防重复提交
340
- ✅ 提交按钮多次点击防抖
341
- ✅ 防止接口雪崩(接口短时间被高频调用)
342
-
343
- ---
344
-
345
- ### ⚠️ 使用注意
346
-
347
- - 本功能专为短时防重复设计,**缓存不持久化**
348
- - 推荐用于 POST、PUT 等存在副作用的接口
349
- - 自动清理缓存,确保下一次请求正常发出
350
-
351
- ---
352
-
353
- ```markdown
354
- # 🚀 并发请求控制器 `createConcurrentPoolRequestor`
355
-
356
- 提供智能并发控制与自动重试能力的请求扩展器,适用于需要精准控制请求并发的场景。
357
-
358
- ---
359
-
360
- ## 📦 核心模块
361
-
362
- ### 1. 并发池 `ConcurrentPool`
81
+ ### 同步请求器(syncRequestor)
363
82
  ```typescript
364
- export class ConcurrentPool {
365
- parallelCount: number // 最大并行任务数
366
- tasks: TaskItemList // 待执行任务队列
367
- runningCount: number // 当前运行中任务数
368
-
369
- constructor(parallelCount = 4) // 初始化并发池
370
-
371
- // 添加任务到队列
372
- add(id: string, task: Task): Promise<any>
373
-
374
- // 移除指定任务
375
- remove(id: string): void
376
-
377
- // 执行单个任务(内部方法)
378
- private execute(currentTask: TaskItem): void
379
-
380
- // 启动任务处理(内部调度器)
381
- private _run(): void
83
+ {
84
+ persist?: false
85
+ sync?: true
382
86
  }
383
87
  ```
88
+ 入参与 cacheRequestor 一致,不能采用异步方案,第一次请求自动报错,之后再次请求均可同步获取
384
89
 
385
- ---
386
-
387
- ### 2. 请求器工厂函数
90
+ ### 并发池请求器(concurrentPoolRequestor)
388
91
  ```typescript
389
- createConcurrentPoolRequestor(config): {
390
- requestor: Requestor, // 增强后的请求器实例
391
- concurrentPool: ConcurrentPool // 关联的并发池
92
+ {
93
+ maxConcurrent: number
94
+ queueTimeout?: number
392
95
  }
393
96
  ```
97
+ - **maxConcurrent**:最大并行请求数量,默认为4
98
+ 其他参数继承于重试请求器
394
99
 
395
- ---
396
-
397
- ## ⚙️ 配置参数
398
-
399
- | 参数 | 类型 | 说明 | 默认值 |
400
- |------------------|---------------------------------------|------------------------------|---------------------|
401
- | `parallelCount` | `number` | 最大并行请求数 | 4 |
402
- | `createId` | `(config: UnifiedConfig) => string` | 生成唯一任务ID的函数 | 时间戳+随机数 |
403
- | `retries` | `number` | 失败重试次数 | 0 (不重试) |
404
-
405
- ---
406
-
407
- ## 🎯 功能特性
408
-
409
- ### 1. 智能并发控制
410
- ```mermaid
411
- graph TD
412
- A[新请求到达] --> B{运行中任务 < 最大并发数?}
413
- B -->|是| C[立即执行]
414
- B -->|否| D[进入等待队列]
415
- C --> E[任务完成]
416
- E --> F{队列有等待任务?}
417
- F -->|是| G[触发下一个任务]
418
- ```
419
-
420
- ### 2. 自动重试机制
100
+ ### 重试请求器(retryRequestor)
421
101
  ```typescript
422
- // 集成重试模块的工作流
423
- sequenceDiagram
424
- participant P as 并发池
425
- participant R as 重试模块
426
- participant S as 服务器
427
-
428
- P->>R: 执行请求
429
- R->>S: 尝试请求
430
- alt 成功
431
- S-->>R: 返回数据
432
- R-->>P: 传递结果
433
- else 失败
434
- R->>R: 重试逻辑(最多retries次)
435
- R-->>P: 最终结果/错误
436
- end
102
+ {
103
+ retries?: number
104
+ delay?: number | (attempt: number) => number
105
+ retryCondition?: (error: any) => boolean
106
+ }
437
107
  ```
108
+ - **retries**:最大重试次数(默认3次)
109
+ - **delay**:重试延迟时间,支持固定数值或动态计算函数
110
+ - **retryCondition**:触发重试的条件判断函数
438
111
 
439
- ---
440
112
 
441
- ## 📝 使用示例
442
-
443
- ### 基础使用
444
113
  ```typescript
445
- import createConcurrentPoolRequestor from '@/requests/modules/concurrentPoolRequestor'
446
-
447
- // 创建最大并发数为3的请求器
448
- const { requestor } = createConcurrentPoolRequestor({
449
- parallelCount: 3,
450
- retries: 2, // 失败自动重试2次
451
- delay: 500 // 重试间隔500ms
452
- })
453
-
454
- // 批量发起请求
455
- const requests = Array(10).fill(0).map(() =>
456
- requestor.get('/api/data')
457
- )
458
-
459
- Promise.all(requests).then(results => {
460
- console.log('所有请求完成:', results)
461
- })
114
+ import { requestExtender } from '@net-vert/core';
462
115
  ```
463
116
 
464
- ### 高级控制
117
+ **缓存请求例子**
465
118
  ```typescript
466
- // 获取并发池实例进行精细控制
467
- const { requestor, concurrentPool } = createConcurrentPoolRequestor()
468
-
469
- // 动态调整并发数
470
- concurrentPool.parallelCount = 5
471
-
472
- // 取消特定请求
473
- const reqId = 'custom-id-123'
474
- requestor.post('/api/submit', { data }, {
475
- __id: reqId // 通过配置注入自定义ID
476
- }).catch(err => {
477
- if (err.message === 'ABORTED') {
478
- console.log('请求被主动取消')
479
- }
480
- })
481
-
482
- // 主动取消任务
483
- concurrentPool.remove(reqId)
119
+ const {requestor} = requestExtender.cacheRequestor();
120
+ requestor.get('/user/info', { params: { id: 1 } });
484
121
  ```
485
122
 
486
- ---
487
-
488
- ## ⚠️ 注意事项
489
-
490
- 1. **ID生成策略**
491
- 确保`createId`函数生成的ID具有唯一性:
492
- ```typescript
493
- createId: config => `${config.method}:${config.url}:${hash(config.params)}`
494
- ```
495
-
496
- 2. **资源释放**
497
- 长时间运行的实例需手动释放资源:
498
- ```typescript
499
- // 清空任务队列
500
- concurrentPool.tasks.clear()
501
- ```
502
-
503
- ---
504
-
505
- ## 🛠 设计理念
506
-
507
- ### 1. 队列优先级策略
508
- ```typescript
509
- // 可扩展为优先级队列
510
- interface PriorityTaskItem extends TaskItem {
511
- priority: number
512
- }
513
-
514
- // 自定义队列实现
515
- class PriorityQueue implements TaskItemList {
516
- enqueue(id: string, item: PriorityTaskItem) {
517
- // 根据优先级插入队列
518
- }
519
- }
520
- ### 1. 队列优先级策略
521
- ```typescript
522
- 一个实例对象控制着单独的并发池
523
-
524
- ```
525
123
 
526
124
  ## 📤 开源信息
527
125
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@net-vert/core",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Dependency Inversion Network Library with Type-Safe Injection.",
5
5
  "main": "dist/index",
6
6
  "type": "module",