@anjianshi/utils 3.8.1 → 3.8.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anjianshi/utils",
3
- "version": "3.8.1",
3
+ "version": "3.8.3",
4
4
  "description": "Common JavaScript Utils",
5
5
  "homepage": "https://github.com/anjianshi/js-packages/utils",
6
6
  "bugs": {
@@ -39,11 +39,11 @@
39
39
  "typescript": "^5.8.3",
40
40
  "vconsole": "^3.15.1",
41
41
  "@anjianshi/presets-eslint-node": "6.1.2",
42
- "@anjianshi/presets-prettier": "3.2.0",
43
- "@anjianshi/presets-eslint-typescript": "6.1.2",
44
42
  "@anjianshi/presets-eslint-react": "6.1.3",
45
43
  "@anjianshi/presets-typescript": "3.2.5",
46
- "@anjianshi/presets-eslint-base": "6.1.2"
44
+ "@anjianshi/presets-prettier": "3.2.0",
45
+ "@anjianshi/presets-eslint-base": "6.1.2",
46
+ "@anjianshi/presets-eslint-typescript": "6.1.2"
47
47
  },
48
48
  "prettier": "@anjianshi/presets-prettier/prettierrc"
49
49
  }
@@ -12,6 +12,7 @@ export declare abstract class BaseRequestClient<FailedT extends Failed> {
12
12
  /** 生成一个快捷方式函数,调用它相当于调用 client.request() */
13
13
  asFunction(): <T>(inputUrl: string, inputOptions?: Options<T>) => Promise<Result<T, FailedT>>;
14
14
  request<T>(inputUrl: string, inputOptions?: Options<T>): Promise<Result<T, FailedT>>;
15
+ protected realRequest<T>(options: FormattedOptions): Promise<Result<T, FailedT>>;
15
16
  formatOptions<T>(input: Options<T>): Promise<FormattedOptions<T>>;
16
17
  /** 请求发起前调用此方法补充 Headers 内容 */
17
18
  protected getHeaders(options: FormattedOptions, inputOptions: Options): Record<string, string> | undefined | Promise<Record<string, string> | undefined>;
@@ -35,7 +36,7 @@ export declare abstract class BaseRequestClient<FailedT extends Failed> {
35
36
  * - 输出 Success 或 Failed 结果均可,但输出的 Failed 结果不会交给 makeFailedResult() 进行格式化,需自行保证符合 FailedT 约定。
36
37
  * - 若此方法抛出异常,会生成 FormatResponseDataFailed,此错误会照常交给 makeFailedResult() 处理。
37
38
  */
38
- protected formatSuccessResult(result: Success<unknown>): Result<unknown, FailedT>;
39
+ protected formatSuccessResult(result: Success<unknown>, options: FormattedOptions): Result<unknown, FailedT>;
39
40
  }
40
41
  /** 默认的 RequestClient 实现。出现错误时,会把错误对象原样放入错误信息中。 */
41
42
  export declare class RequestClient extends BaseRequestClient<RequestFailed> {
package/request/client.js CHANGED
@@ -30,6 +30,18 @@ export class BaseRequestClient {
30
30
  url: inputUrl,
31
31
  ...(inputOptions ?? {}),
32
32
  });
33
+ let result;
34
+ let tryCount = 0;
35
+ do {
36
+ tryCount += 1;
37
+ if (tryCount > 1) {
38
+ this.logger.warn('Retrying Request', { ...options, tryCount });
39
+ }
40
+ result = await this.realRequest(options);
41
+ } while (!result.success && tryCount <= options.retry + 1);
42
+ return result;
43
+ }
44
+ async realRequest(options) {
33
45
  const { url, method, headers, body, timeout, signal: manualSignal, format } = options;
34
46
  const timeoutSignal = timeout ? AbortSignal.timeout(timeout) : undefined;
35
47
  const signal = manualSignal || timeoutSignal
@@ -71,7 +83,7 @@ export class BaseRequestClient {
71
83
  // 格式化响应数据
72
84
  if (result.success) {
73
85
  try {
74
- result = this.formatSuccessResult(result);
86
+ result = this.formatSuccessResult(result, options);
75
87
  }
76
88
  catch (error) {
77
89
  return this.handleError(failed('Format Response Data Failed', 'FormatResponseDataFailed', {
@@ -103,7 +115,7 @@ export class BaseRequestClient {
103
115
  // -------------------------------
104
116
  async formatOptions(input) {
105
117
  const predefined = this.prefefinedOptions;
106
- const { urlPrefix = predefined.urlPrefix ?? '', url: rawUrl, query = {}, method = predefined.method ?? 'GET', headers: rawHeaders = {}, body: rawBody = null, data, timeout = predefined.timeout ?? 0, binary = false, signal, format, } = input;
118
+ const { urlPrefix = predefined.urlPrefix ?? '', url: rawUrl, query = {}, method = predefined.method ?? 'GET', headers: rawHeaders = {}, body: rawBody = null, data, binary = false, timeout = predefined.timeout ?? 0, signal, retry = predefined.retry ?? 0, format, } = input;
107
119
  const headers = {
108
120
  ...(predefined.headers ?? {}),
109
121
  ...rawHeaders,
@@ -128,6 +140,7 @@ export class BaseRequestClient {
128
140
  binary,
129
141
  signal,
130
142
  format,
143
+ retry,
131
144
  };
132
145
  Object.assign(options.headers, await this.getHeaders(options, input));
133
146
  return options;
@@ -205,7 +218,9 @@ export class BaseRequestClient {
205
218
  * - 输出 Success 或 Failed 结果均可,但输出的 Failed 结果不会交给 makeFailedResult() 进行格式化,需自行保证符合 FailedT 约定。
206
219
  * - 若此方法抛出异常,会生成 FormatResponseDataFailed,此错误会照常交给 makeFailedResult() 处理。
207
220
  */
208
- formatSuccessResult(result) {
221
+ formatSuccessResult(result,
222
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
223
+ options) {
209
224
  return result;
210
225
  }
211
226
  }
@@ -19,10 +19,12 @@ export interface Options<T = unknown> {
19
19
  timeout?: number;
20
20
  /** 可通过此信号手动终止请求 */
21
21
  signal?: AbortSignal;
22
+ /** 请求结果为失败(无论原因为何)时的重试次数,默认值为 0,表示不重试 */
23
+ retry?: number;
22
24
  /** 对请求成功时得到的数据进行最终格式化 */
23
25
  format?: (responseData: any) => T;
24
26
  }
25
27
  /** 可预指定的请求参数 */
26
- export type PredefinedOptions = Pick<Options, 'urlPrefix' | 'method' | 'headers' | 'timeout'>;
28
+ export type PredefinedOptions = Pick<Options, 'urlPrefix' | 'method' | 'headers' | 'timeout' | 'retry'>;
27
29
  /** 经过整理的请求参数(client 内部使用) */
28
- export type FormattedOptions<T = unknown> = Required<Pick<Options, 'url' | 'method' | 'headers' | 'body' | 'timeout' | 'binary'>> & Pick<Options<T>, 'signal' | 'format'>;
30
+ export type FormattedOptions<T = unknown> = Required<Pick<Options, 'url' | 'method' | 'headers' | 'body' | 'binary' | 'timeout' | 'retry'>> & Pick<Options<T>, 'signal' | 'format'>;