0.0.15 • Published 12 months ago

@pluve/fetch2 v0.0.15

Weekly downloads
-
License
ISC
Repository
gitlab
Last release
12 months ago

@pluve/fetch2

基于 fetch 封装,保留与@pluve/fetch基本一致的用法。若用到文件上传,请参考@pluve/file-utility或者@pluve/storage-client

安装

yarn add @pluve/fetch2

引用

import FetchAgent from '@pluve/fetch2';

使用说明

@pluve/fetch 支持自定义请求头,可动态设置鉴权 token,实现了请求和响应结果拦截器,可对响应报文统一处理。支持超时时间配置,debug 模式,支持终止请求等。

类型说明

IRequestParams

interface RequestInit {
  /** A BodyInit object or null to set request's body. */
  body?: BodyInit | null;
  /** A string indicating how the request will interact with the browser's cache to set request's cache. */
  cache?: RequestCache;
  /** A string indicating whether credentials will be sent with the request always, never, or only when sent to a same-origin URL. Sets request's credentials. */
  credentials?: RequestCredentials;
  /** A Headers object, an object literal, or an array of two-item arrays to set request's headers. */
  headers?: HeadersInit;
  /** A cryptographic hash of the resource to be fetched by request. Sets request's integrity. */
  integrity?: string;
  /** A boolean to set request's keepalive. */
  keepalive?: boolean;
  /** A string to set request's method. */
  method?: string;
  /** A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode. */
  mode?: RequestMode;
  /** A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect. */
  redirect?: RequestRedirect;
  /** A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer. */
  referrer?: string;
  /** A referrer policy to set request's referrerPolicy. */
  referrerPolicy?: ReferrerPolicy;
  /** An AbortSignal to set request's signal. */
  signal?: AbortSignal | null;
  /** Can only be null. Used to disassociate request from any Window. */
  window?: null;
}
export interface IRequestParams extends RequestInit {
  key?: string; // 接口请求标识,用于取消请求
  url: string; // 接口请求链接
  method?: RequestMethodsEnum; // 请求方式
  headers?: ICustomHeader; // 接口请求头,可与全局的请求头合并
  useGlobalHeader?: boolean; // 是否使用全局请求头
  body?: any; // 请求体
  submitDataType?: 'json' | 'form'; // 数据提交类型,支持application/json 和  application/x-www-form-urlencoded
  timeout?: number; // 接口超时时间,单位毫秒,默认15000
  timeStamp?: number; // 接口发起时的时间戳
  abortController?: AbortController; // 取消请求的控制器
  reqInterceptor?: IRequestInterceptor; // 请求拦截器
  respInterceptor?: IResponseInterceptor; // 响应拦截器
  [key: string]: any; // 支持携带自定义请求参数,可在拦截器中使用
}
Response
interface Body {
  readonly body: ReadableStream<Uint8Array> | null;
  readonly bodyUsed: boolean;
  arrayBuffer(): Promise<ArrayBuffer>;
  blob(): Promise<Blob>;
  formData(): Promise<FormData>;
  json(): Promise<any>;
  text(): Promise<string>;
}
interface Response extends Body {
  readonly headers: Headers;
  readonly ok: boolean;
  readonly redirected: boolean;
  readonly status: number;
  readonly statusText: string;
  readonly type: ResponseType;
  readonly url: string;
  clone(): Response;
}

IExceptionInfo

export interface IExceptionInfo {
  code: number; // EXCEPTION_KEYS
  message: string;
  data?: string | number;
}
const EXCEPTION_KEYS = {
  ABORT_EXCEPTION_KEY: 10000, // 请求终止
  TIMEOUT_EXCEPTION_KEY: 10001, // 请求超时
  NETWORK_ERROR_EXCEPTION_KEY: 10002, // 请求网络异常
  INTERCEPT_AT_GLOBAL_LEVEL: 10003, // 被全局拦截器拦截
  INTERCEPT_AT_API_LEVEL: 10004, // 被接口拦截器拦截
  REQUEST_REDIRECT: 10005, // 请求重定向
  RESPONSE_400_PLUS: 10006, // 400相关响应
  RESPONSE_OTHER: 10007, // 其他异常
  REQUEST_CROSS: 10008, // 请求跨域
  RESPONSE_TIME_TRIGGER_THRESHOLD: 10009, // 接口耗时触发阀值
};

接口

setDebug

设置是否为 debug 模式。debug 模式下,控制台会打印详细的接口请求及响应信息,默认为关闭,可在开发测试模式下开启,建议在生产环境关闭。

FetchAgent.setDebug(true);

setupTimeout

设置超时时间,默认为 15s,单位为毫秒

FetchAgent.setTimeout(15000);

setupApiTimeCostThreshold

设置接口响应时长阀值,默认 1000ms,超过该值则会在控制台打印接口响应时长

FetchAgent.setupApiTimeCostThreshold(1000);

setupDefaultGlobalHeaderGenerator

设置统一请求头信息,若某个接口请求头有特殊要求,可在 GET、POST 方法中设置

FetchAgent.setupDefaultGlobalHeaderGenerator(() => ({
  'Content-Type': 'application/json',
  'X-Requested-With': 'XMLHttpRequest',
}));

setupDefaultCommonReqBodyGenerator

在请求体中设置通用参数,如鉴权信息等。若表单提交,则会忽略该方法设置的参数。

FetchAgent.setupDefaultCommonReqBodyGenerator(() => ({
  openx_header: 'xxx',
}));

setupReqInterceptor

接口请求全局拦截器,若返回 true,则终止请求。接口级别的拦截器优先级高于全局拦截器。

FetchAgent.setupReqInterceptor((req: IRequestParams) => false);

setupRespInterceptor

响应结果全局拦截器,若返回 true,则终止后续流程。可用于 token 过期、异常处理等场景。接口级别的拦截器优先级高于全局拦截器。此处读取 response 响应数据应先 clone,否在 return false 后会导致响应体重复使用的异常。

FetchAgent.setupRespInterceptor((requestParams: IRequestParams, response: Response) => false);

setupOnError

设置全局错误处理函数 接口响应码非 200 时会回调;\ 接口响应超时时会回调;\ 接口响应时长超过警告阀值时会回调;\ 可在异常日志上报场景下使用。

FetchAgent.setupOnError((err: IExceptionInfo, requestInfo: IRequestParams) => {
  console.log(error);
});

sendRequest

发送请求\ ① 返回 Promise,若请求被拦截,则返回 undefined。\ ② 支持 GET、POST、PUT、DELETE、PATCH 等请求方式。\ ③ 支持请求头、请求体、请求参数、请求超时、请求取消等功能。\ ④ 支持传入泛型,返回指定类型的数据。

/**
 * 发送请求
 * @param requestInfo
 */
export const request = <T = unknown>(requestInfo: IRequestParams): Promise<T> => {
  const requestParams = buildRequestOptions(requestInfo);
  if (requestParams.reqInterceptor && requestParams.reqInterceptor(requestParams)) {
    return;
  }
  if (handlerBeforeRequest(requestParams)) {
    return;
  }
  requestMap.set(requestParams.key, requestParams);
  const apiPromise = doRequest(requestParams);
  return handlerApiResponse<T>(requestParams, apiPromise);
};

// 业务服务声明
export const fetchArticle = ({ pageNo, pageSize }: { pageNo: number; pageSize: number }) =>
  FetchAgent.sendPost<ApiCommonResponse<IArticleDataItem[]>>({
    url: articleService,
    body: {
      article: { articleType: null, keyword: null },
      pageNo,
      pageSize,
    },
    respInterceptor: async (requestParams, response) => {
      console.log('respInterceptor: ', requestParams);
      // 一定要这样写
      // console.log(response.clone().json());
      // 这样写报错
      // console.log(response.json());
      return false;
    },
  });

// 业务调用
try {
  const articleListResp = await fetchArticle({ pageNo: this.pageNo, pageSize: this.pageSize });
  this.updateArticles(refresh, articleListResp);
} catch (e) {
  this.showError();
}

为了兼容@pluve/fetch,request 接口有以下变种 | 编号 | 方法名 | 说明 | | -- | -- | -- | | 1 | sendRequest | 发送接口请求 | | 2 | sendRequestCustomer | 发送接口请求 | | 3 | sendRequestPure | 发送接口请求 | | 4 | get | 发送 get 请求 | | 5 | sendGet | 发送 get 请求 | | 6 | post | 发送 post 请求 | | 7 | sendPost | 发送 post 请求 |

abortPendingRequestByKey

根据 key 终止请求

export const abortPendingRequestByKey = (key: string) => {
  if (!key) {
    return;
  }
  const requestItem = requestMap[key] as IRequestParams;
  if (requestItem && requestItem.abortController) {
    requestAbortManualFlag.set(key, true);
    requestItem.abortController.abort();
    requestMap.delete(key);
  }
};
FetchAgent.abortPendingRequestByKey('key');

clearRequest

清除 pending 中的请求

export const clearRequest = () => {
  // 只要还在此map中的请求,均为pending状态
  requestMap.forEach(requestItem => {
    if (requestItem.abortController) {
      const key = requestItem.key || '';
      requestAbortManualFlag.set(key, true);
      requestItem.abortController.abort();
    }
  });
  requestMap.clear();
};
FetchAgent.clearRequest();

外部依赖

若低版本浏览器需要依赖 whatwg-fetch

issues 说明

暂无版本计划

0.0.13

12 months ago

0.0.14

12 months ago

0.0.15

12 months ago

0.0.10

1 year ago

0.0.11

1 year ago

0.0.12

1 year ago

0.0.9

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.1

1 year ago