npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@pluve/fetch2

v0.0.15

Published

fetch abort

Downloads

9

Readme

@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 说明

暂无版本计划