@seayoo-web/request 1.2.2 → 1.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.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  市面上流行的网络请求工具有以下一些限制或不足:
6
6
 
7
7
  1. 体积过大
8
- 2. 流行的几个 request 工具均不支持重试配置
8
+ 2. 流行的几个 request 工具均不默认支持重试配置
9
9
  3. 对响应结果不进行更多检查(无类型守卫,无结构分析),无法完美对接 ts 代码
10
10
  4. 功能过于冗余,而相当多特性实际开发中使用不到
11
11
 
@@ -48,6 +48,8 @@ export async function getUserList(): Promise<IUser[]> {
48
48
  import { setGlobalConfig } from "@seayoo-web/request"
49
49
  // nodejs 环境
50
50
  import { setGlobalConfig } from "@seayoo-web/request/node"
51
+ // 或在某些编译配置或编辑器中无法识别上述路径,可以改用实际的 dist 路径导入
52
+ import { setGlobalConfig } from "@seayoo-web/request/dist/node"
51
53
 
52
54
  // 以下是默认的全局配置(更多介绍请参考下方全局配置)
53
55
  setGlobalConfig({
@@ -147,7 +149,7 @@ setConfig({ timeout: 5000 })
147
149
 
148
150
  说明:用于指定如何解析响应体内容
149
151
 
150
- - **FailedRule**: { resolve, messageField? }
152
+ - **FailedRule**: { resolve, statusField?, messageField? }
151
153
 
152
154
  http失败时 (status <200 || status >= 400) 解析策略
153
155
 
@@ -155,6 +157,10 @@ setConfig({ timeout: 5000 })
155
157
 
156
158
  ​ 解析方式,设置为 json(默认),则可以进一步指定错误消息字段;设置为 body 则将整个 body 解析为错误信息;
157
159
 
160
+ **statusField**: string
161
+
162
+ ​ 解析错误消息的状态字段,仅在 resolve 为 json 时有效,有值的话会替换 response 的 code
163
+
158
164
  **messageField**: string | string[]
159
165
 
160
166
  ​ 错误消息解析字段,仅在 resolve 为 json 时有效,默认值 "message"
@@ -169,15 +175,15 @@ setConfig({ timeout: 5000 })
169
175
 
170
176
  **statusField**: string
171
177
 
172
- 指定表示自定义状态的字段名,默认是 "code"
178
+ 指定表示自定义状态的字段名,默认是 "code"
173
179
 
174
180
  **statusOKValue**: string
175
181
 
176
182
  ​ 指定表示自定义状态成功时的 value,默认是 "0",如果响应值为数字,则会被转化为字符串进行处理
177
183
 
178
- **dataField**: string
184
+ **dataField**: string | true
179
185
 
180
- ​ 指定表示响应数据的字段,默认是 "data"
186
+ ​ 指定表示响应数据的字段,默认是 "data",如果设置为 true,则将整个 json body 作为数据内容返回
181
187
 
182
188
  **messageField**: string | string[]
183
189
 
@@ -191,29 +197,47 @@ setConfig({ timeout: 5000 })
191
197
 
192
198
  类型:number
193
199
 
194
- 说明:当请求发生错误时重试的次数,默认0,最大为 10
200
+ 说明:当请求发生错误时重试的次数,默认0,即不重试,最大为 10
195
201
 
196
202
  ### retryResolve
197
203
 
198
- 类型:"network" | "status"
204
+ 类型:"network" | "status" | number[] | ((result: IRequestBaseResponse, count: number) => boolean)
205
+
206
+ 说明:重试判断方法,默认是 network
207
+
208
+ network 表示仅仅当网络错误时才重试;
199
209
 
200
- 说明:重试判断方法,network 表示仅仅当网络错误时才重试;status 表示网络错误或者状态码错误时重试; 默认是 network
210
+ status 表示网络错误或者http 状态码错误时重试;
211
+
212
+ 当设置为 number[] 时,将检查 http 状态码,匹配则重试;
213
+
214
+ 也可以设置为一个重试检查函数,返回 true 则进行重试;
201
215
 
202
216
  ### retryInterval
203
217
 
204
- 类型:number | ((retryIndex: number) => number)
218
+ 类型:number | "2EB" | ((retryIndex: number) => number)
219
+
220
+ 说明:两次重试的间隔策略,设置为数字(单位 ms)表示固定间隔,设置为函数则可以自定义间隔;
221
+
222
+ 其中 retryIndex 从 1 开始,最大为 10;最小时间间隔为 100ms;
205
223
 
206
- 说明:两次重试的间隔策略,设置为数字(单位 ms)表示固定间隔,设置为函数则可以自定义间隔;其中 retryIndex 1 开始,最大为 10;最小时间间隔为 100ms;
224
+ 特殊值 2EB 表示以 2 为底的[指数退避策略](https://en.wikipedia.org/wiki/Exponential_backoff),即首次重试等待 1 秒,后续分别是 2秒,4秒,8秒 ...
207
225
 
208
- ### requestHandler
226
+ ### requestTransformer
209
227
 
210
- 类型:null | ((headers: Record<string, string>, params: Record<string, string>, method: string, url: string) => MaybePromise<void | string>)
228
+ 类型:null | ((data: {
229
+ headers: Record<string, string>,
230
+ params: Record<string, string>,
231
+ method: string,
232
+ url: string,
233
+ body: IBaseRequestBody
234
+ }) => MaybePromise<void | string>)
211
235
 
212
- 说明:同时兼具 transformer 的功能,可用于发送前修改请求相关数据
236
+ 说明:可用于发送前修改请求相关数据,通常用于追加认证信息或签名信息
213
237
 
214
238
  - 发送前用于修改 headers 或 params 的函数,headers 和 params 为引用数据,可以直接修改或追加内容;
215
239
  - 函数如果返回一个非空字符串,则当作 url 地址使用,原有的 url 地址将被替换;
216
- - 通常用于全局追加 header 自定义认证信息;
240
+ - 通常用于全局追加 header 自定义认证信息或签名信息;
217
241
 
218
242
  ### errorHandler
219
243
 
@@ -237,7 +261,7 @@ setConfig({ timeout: 5000 })
237
261
 
238
262
  类型:null | ((data: IRequestLog) => void)
239
263
 
240
- 说明:全局日志打印函数,目前仅仅输出请求开始和完成的日志,具体日志信息可参考 types 声明;
264
+ 说明:全局日志打印函数,具体日志信息可参考源码类型声明;
241
265
 
242
266
  ## 网络请求参数
243
267
 
@@ -285,11 +309,11 @@ setConfig({ timeout: 5000 })
285
309
 
286
310
  ### retryResolve
287
311
 
288
- 同全局配置,仅本次请求有效,设置重试判断策略,默认 network,可选 status
312
+ 同全局配置,仅本次请求有效,设置重试判断策略,默认 network
289
313
 
290
314
  ### retryInterval
291
315
 
292
- 同全局配置,仅本次请求有效,设置两次请求中间的间隔,单位 ms,可以设置为数字或返回数字的函数
316
+ 同全局配置,仅本次请求有效,默认 1000ms
293
317
 
294
318
  ## 响应内容
295
319
 
@@ -325,7 +349,7 @@ setConfig({ timeout: 5000 })
325
349
 
326
350
  ### headers
327
351
 
328
- 类型:Record<string, string | undefined>
352
+ 类型:Record<string, string | undefined>
329
353
 
330
354
  说明:响应的头信息,全部字段名均被转成小写
331
355
 
@@ -433,7 +457,7 @@ const { ok, data } = await post(url, formData, typeGuard);
433
457
 
434
458
  ```typescript
435
459
  setGlobalConfig({
436
- message: function({ code, status }:IResponseResult, method: string, url: string, defaultMsg: string){
460
+ message: function({ code, status, message }, method, url, defaultMsg){
437
461
  if(code === "NetworkError" || code === "Failed" || code === "Aborted") {
438
462
  return "⚠️ 网络错误,请检查网络";
439
463
  }
@@ -446,7 +470,7 @@ setGlobalConfig({
446
470
  if(code === "Unknown") {
447
471
  return `⛔ ${url} 出现未知错误,请稍候再试`;
448
472
  }
449
- return defaultMsg;
473
+ return message;
450
474
  }
451
475
  })
452
476
  ```
@@ -0,0 +1,224 @@
1
+ body, html {
2
+ margin:0; padding: 0;
3
+ height: 100%;
4
+ }
5
+ body {
6
+ font-family: Helvetica Neue, Helvetica, Arial;
7
+ font-size: 14px;
8
+ color:#333;
9
+ }
10
+ .small { font-size: 12px; }
11
+ *, *:after, *:before {
12
+ -webkit-box-sizing:border-box;
13
+ -moz-box-sizing:border-box;
14
+ box-sizing:border-box;
15
+ }
16
+ h1 { font-size: 20px; margin: 0;}
17
+ h2 { font-size: 14px; }
18
+ pre {
19
+ font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20
+ margin: 0;
21
+ padding: 0;
22
+ -moz-tab-size: 2;
23
+ -o-tab-size: 2;
24
+ tab-size: 2;
25
+ }
26
+ a { color:#0074D9; text-decoration:none; }
27
+ a:hover { text-decoration:underline; }
28
+ .strong { font-weight: bold; }
29
+ .space-top1 { padding: 10px 0 0 0; }
30
+ .pad2y { padding: 20px 0; }
31
+ .pad1y { padding: 10px 0; }
32
+ .pad2x { padding: 0 20px; }
33
+ .pad2 { padding: 20px; }
34
+ .pad1 { padding: 10px; }
35
+ .space-left2 { padding-left:55px; }
36
+ .space-right2 { padding-right:20px; }
37
+ .center { text-align:center; }
38
+ .clearfix { display:block; }
39
+ .clearfix:after {
40
+ content:'';
41
+ display:block;
42
+ height:0;
43
+ clear:both;
44
+ visibility:hidden;
45
+ }
46
+ .fl { float: left; }
47
+ @media only screen and (max-width:640px) {
48
+ .col3 { width:100%; max-width:100%; }
49
+ .hide-mobile { display:none!important; }
50
+ }
51
+
52
+ .quiet {
53
+ color: #7f7f7f;
54
+ color: rgba(0,0,0,0.5);
55
+ }
56
+ .quiet a { opacity: 0.7; }
57
+
58
+ .fraction {
59
+ font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60
+ font-size: 10px;
61
+ color: #555;
62
+ background: #E8E8E8;
63
+ padding: 4px 5px;
64
+ border-radius: 3px;
65
+ vertical-align: middle;
66
+ }
67
+
68
+ div.path a:link, div.path a:visited { color: #333; }
69
+ table.coverage {
70
+ border-collapse: collapse;
71
+ margin: 10px 0 0 0;
72
+ padding: 0;
73
+ }
74
+
75
+ table.coverage td {
76
+ margin: 0;
77
+ padding: 0;
78
+ vertical-align: top;
79
+ }
80
+ table.coverage td.line-count {
81
+ text-align: right;
82
+ padding: 0 5px 0 20px;
83
+ }
84
+ table.coverage td.line-coverage {
85
+ text-align: right;
86
+ padding-right: 10px;
87
+ min-width:20px;
88
+ }
89
+
90
+ table.coverage td span.cline-any {
91
+ display: inline-block;
92
+ padding: 0 5px;
93
+ width: 100%;
94
+ }
95
+ .missing-if-branch {
96
+ display: inline-block;
97
+ margin-right: 5px;
98
+ border-radius: 3px;
99
+ position: relative;
100
+ padding: 0 4px;
101
+ background: #333;
102
+ color: yellow;
103
+ }
104
+
105
+ .skip-if-branch {
106
+ display: none;
107
+ margin-right: 10px;
108
+ position: relative;
109
+ padding: 0 4px;
110
+ background: #ccc;
111
+ color: white;
112
+ }
113
+ .missing-if-branch .typ, .skip-if-branch .typ {
114
+ color: inherit !important;
115
+ }
116
+ .coverage-summary {
117
+ border-collapse: collapse;
118
+ width: 100%;
119
+ }
120
+ .coverage-summary tr { border-bottom: 1px solid #bbb; }
121
+ .keyline-all { border: 1px solid #ddd; }
122
+ .coverage-summary td, .coverage-summary th { padding: 10px; }
123
+ .coverage-summary tbody { border: 1px solid #bbb; }
124
+ .coverage-summary td { border-right: 1px solid #bbb; }
125
+ .coverage-summary td:last-child { border-right: none; }
126
+ .coverage-summary th {
127
+ text-align: left;
128
+ font-weight: normal;
129
+ white-space: nowrap;
130
+ }
131
+ .coverage-summary th.file { border-right: none !important; }
132
+ .coverage-summary th.pct { }
133
+ .coverage-summary th.pic,
134
+ .coverage-summary th.abs,
135
+ .coverage-summary td.pct,
136
+ .coverage-summary td.abs { text-align: right; }
137
+ .coverage-summary td.file { white-space: nowrap; }
138
+ .coverage-summary td.pic { min-width: 120px !important; }
139
+ .coverage-summary tfoot td { }
140
+
141
+ .coverage-summary .sorter {
142
+ height: 10px;
143
+ width: 7px;
144
+ display: inline-block;
145
+ margin-left: 0.5em;
146
+ background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147
+ }
148
+ .coverage-summary .sorted .sorter {
149
+ background-position: 0 -20px;
150
+ }
151
+ .coverage-summary .sorted-desc .sorter {
152
+ background-position: 0 -10px;
153
+ }
154
+ .status-line { height: 10px; }
155
+ /* yellow */
156
+ .cbranch-no { background: yellow !important; color: #111; }
157
+ /* dark red */
158
+ .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159
+ .low .chart { border:1px solid #C21F39 }
160
+ .highlighted,
161
+ .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162
+ background: #C21F39 !important;
163
+ }
164
+ /* medium red */
165
+ .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166
+ /* light red */
167
+ .low, .cline-no { background:#FCE1E5 }
168
+ /* light green */
169
+ .high, .cline-yes { background:rgb(230,245,208) }
170
+ /* medium green */
171
+ .cstat-yes { background:rgb(161,215,106) }
172
+ /* dark green */
173
+ .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174
+ .high .chart { border:1px solid rgb(77,146,33) }
175
+ /* dark yellow (gold) */
176
+ .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177
+ .medium .chart { border:1px solid #f9cd0b; }
178
+ /* light yellow */
179
+ .medium { background: #fff4c2; }
180
+
181
+ .cstat-skip { background: #ddd; color: #111; }
182
+ .fstat-skip { background: #ddd; color: #111 !important; }
183
+ .cbranch-skip { background: #ddd !important; color: #111; }
184
+
185
+ span.cline-neutral { background: #eaeaea; }
186
+
187
+ .coverage-summary td.empty {
188
+ opacity: .5;
189
+ padding-top: 4px;
190
+ padding-bottom: 4px;
191
+ line-height: 1;
192
+ color: #888;
193
+ }
194
+
195
+ .cover-fill, .cover-empty {
196
+ display:inline-block;
197
+ height: 12px;
198
+ }
199
+ .chart {
200
+ line-height: 0;
201
+ }
202
+ .cover-empty {
203
+ background: white;
204
+ }
205
+ .cover-full {
206
+ border-right: none !important;
207
+ }
208
+ pre.prettyprint {
209
+ border: none !important;
210
+ padding: 0 !important;
211
+ margin: 0 !important;
212
+ }
213
+ .com { color: #999 !important; }
214
+ .ignore-none { color: #999; font-weight: normal; }
215
+
216
+ .wrapper {
217
+ min-height: 100%;
218
+ height: auto !important;
219
+ height: 100%;
220
+ margin: 0 auto -48px;
221
+ }
222
+ .footer, .push {
223
+ height: 48px;
224
+ }
@@ -0,0 +1,87 @@
1
+ /* eslint-disable */
2
+ var jumpToCode = (function init() {
3
+ // Classes of code we would like to highlight in the file view
4
+ var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
5
+
6
+ // Elements to highlight in the file listing view
7
+ var fileListingElements = ['td.pct.low'];
8
+
9
+ // We don't want to select elements that are direct descendants of another match
10
+ var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
11
+
12
+ // Selecter that finds elements on the page to which we can jump
13
+ var selector =
14
+ fileListingElements.join(', ') +
15
+ ', ' +
16
+ notSelector +
17
+ missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
18
+
19
+ // The NodeList of matching elements
20
+ var missingCoverageElements = document.querySelectorAll(selector);
21
+
22
+ var currentIndex;
23
+
24
+ function toggleClass(index) {
25
+ missingCoverageElements
26
+ .item(currentIndex)
27
+ .classList.remove('highlighted');
28
+ missingCoverageElements.item(index).classList.add('highlighted');
29
+ }
30
+
31
+ function makeCurrent(index) {
32
+ toggleClass(index);
33
+ currentIndex = index;
34
+ missingCoverageElements.item(index).scrollIntoView({
35
+ behavior: 'smooth',
36
+ block: 'center',
37
+ inline: 'center'
38
+ });
39
+ }
40
+
41
+ function goToPrevious() {
42
+ var nextIndex = 0;
43
+ if (typeof currentIndex !== 'number' || currentIndex === 0) {
44
+ nextIndex = missingCoverageElements.length - 1;
45
+ } else if (missingCoverageElements.length > 1) {
46
+ nextIndex = currentIndex - 1;
47
+ }
48
+
49
+ makeCurrent(nextIndex);
50
+ }
51
+
52
+ function goToNext() {
53
+ var nextIndex = 0;
54
+
55
+ if (
56
+ typeof currentIndex === 'number' &&
57
+ currentIndex < missingCoverageElements.length - 1
58
+ ) {
59
+ nextIndex = currentIndex + 1;
60
+ }
61
+
62
+ makeCurrent(nextIndex);
63
+ }
64
+
65
+ return function jump(event) {
66
+ if (
67
+ document.getElementById('fileSearch') === document.activeElement &&
68
+ document.activeElement != null
69
+ ) {
70
+ // if we're currently focused on the search input, we don't want to navigate
71
+ return;
72
+ }
73
+
74
+ switch (event.which) {
75
+ case 78: // n
76
+ case 74: // j
77
+ goToNext();
78
+ break;
79
+ case 66: // b
80
+ case 75: // k
81
+ case 80: // p
82
+ goToPrevious();
83
+ break;
84
+ }
85
+ };
86
+ })();
87
+ window.addEventListener('keydown', jumpToCode);