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

@beisen/fetch

v2.0.2

Published

A platform fetch tool based on fetch.

Downloads

54

Readme

@beisen/fetch

基于北森业务定制的简单统一的网络请求库


支持的功能

  • url 参数自动序列化
  • post 数据提交方式简化
  • response 返回处理简化
  • 超时支持
  • 重试机制
  • 取消请求
  • 统一的错误处理方式
  • request 和 response 拦截器(interceptors)支持

安装

npm install --save @beisen/fetch

API

可以通过向 BSFetch 传参来发起请求

BSFetch(url[, options])

import BSFetch from '@beisen/fetch';

BSFetch('/api/v1/xxx', {
    method: 'get',
    params: { id: 1 }
  })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

BSFetch('/api/v1/user', {
    method: 'post',
    data: {
      name: 'Mike'
    }
  })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

请求方法的别名

为了方便起见,为所有支持的请求方法提供了别名, method 属性不必在配置中指定

BSFetch.get(url[, options])

BSFetch.put(url[, options])

BSFetch.post(url[, options])

BSFetch.delete(url[, options])

BSFetch.head(url[, options])

BSFetch.options(url[, options])

BSFetch.patch(url[, options])

快速上手

执行 GET 请求

import BSFetch from '@beisen/fetch';

BSFetch.get('/api/v1/xxx?id=1')
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

// 也可将 URL 的参数放到 options.params 里
BSFetch.get('/api/v1/xxx', {
    data: {
      id: 1
    }
  })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

执行 POST 请求

BSFetch.post('/api/v1/user', {
    data: {
      name: 'Mike'
    }
  })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

创建实例

有些通用的配置我们不想每个请求里都去添加,那么可以通过 create 新建一个实例

create([options])

import { create } from '@beisen/fetch';

const BSFetch = create({
  timeout: 1000,
  headers: {
    'Content-Type': 'multipart/form-data'
  }
});

BSFetch.get('/user')
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

请求配置

BSFetch options 参数

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | :--- | :--- | :--- | :--- | :--- | | method | 请求方式 | string | get , post , put ... | get | | baseUrl | url前缀| string | -- | -- | | retries | 重试次数 | number | -- | -- | | retryDelay | 重试间隔 | number or function(attempt, error, response) | -- | -- | | retryOn | 指定重试条件 | Array<httpcode>[] or function(attempt, error, response) | -- | -- | | data | 提交的数据或者url请求参数 | any | -- | -- | | headers | fetch 原有参数 | object | -- | {} | | headers | fetch 原有参数 | object | -- | {} | | timeout | 超时时长, 默认毫秒, 写操作慎用 | number | -- | -- | | credentials | fetch 请求包含 cookies 信息 | object | -- | same-origin | | enableKongHeaders | 启用kong相关字段 | boolean | -- | true | | timeStamp | 时间戳,get请求是否追加时间戳 | boolean | -- | true | | requestType | post请求时数据类型 | string | json , form | json | | parseResponse | 是否对 response 做处理简化 | boolean | -- | true | | charset | 字符集 | string | utf8 , gbk | utf8 | | responseType | 如何解析返回的数据 | string | json , text , blob , formData ... | json , text | | throwErrIfParseFail | 当 responseType 为 'json', 对请求结果做 JSON.parse 出错时是否抛出异常 | boolean | -- |false | | getResponse | 是否获取源response, 返回结果将包裹一层 | boolean | -- | fasle | | errorHandler | 异常处理, 或者覆盖统一的异常处理 | function(error) | -- | | cancelToken | 取消请求的 Token | CancelToken.token | -- | -- |

fetch原其他参数有效, 详见fetch文档

create options 初始化默认参数, 支持以上所有

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | :--- | :--- | :--- | :--- | :--- | | method | 请求方式 | string | get , post , put ... | get | | params | url请求参数 | object | -- | -- | | data | 提交的数据 | any | -- | -- | | ... |

{
  // 'method' 是创建请求时使用的方法
  method: 'get', // default

  // 'params' 是即将于请求一起发送的 URL 参数,参数会自动 encode 后添加到 URL 中
  // 类型需为 Object 对象或者 URLSearchParams 对象
  params: { id: 1 },

  // 'paramsSerializer' 开发者可通过该函数对 params 做序列化(注意:此时传入的 params 为合并了 extends 中 params 参数的对象,如果传入的是 URLSearchParams 对象会转化为 Object 对象
  paramsSerializer: function (params) {
    return Qs.stringify(params, { arrayFormat: 'brackets' })
  },

  // 'data' 作为请求主体被发送的数据
  // 适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  data: { name: 'Mike' },

  // 'headers' 请求头
  headers: { 'Content-Type': 'multipart/form-data' },

  // 'timeout' 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求超过了 'timeout' 时间,请求将被中断并抛出请求异常
  timeout: 1000,
  // 是否自动添加时间戳,用来防止缓存(仅get方法)
  timeStamp: true,
  // 是否自动kong网关相关header
  enableKongHeaders: true,

  // 'credentials' 发送带凭据的请求
  // 为了让浏览器发送包含凭据的请求(即使是跨域源),需要设置 credentials: 'include'
  // 如果只想在请求URL与调用脚本位于同一起源处时发送凭据,请添加credentials: 'same-origin'
  // 要改为确保浏览器不在请求中包含凭据,请使用credentials: 'omit'
  credentials: 'same-origin', // default


  // 'requestType' 当 data 为对象或者数组时,会根据 requestType 动态添加 headers 和设置 body(可传入 headers 覆盖 Accept 和 Content-Type 头部属性):
  // 1. requestType === 'json' 时, (默认为 json )
  // options.headers = {
  //   Accept: 'application/json',
  //   'Content-Type': 'application/json;charset=UTF-8',
  //   ...options.headers,
  // }
  // options.body = JSON.stringify(data)
  // 2. requestType === 'form' 时,
  // options.headers = {
  //   Accept: 'application/json',
  //   'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
  //   ...options.headers,
  // };
  // options.body = query-string.stringify(data);
  // 3. 其他 requestType
  // options.headers = {
  //   Accept: 'application/json',
  //   ...options.headers,
  // };
  // options.body = data;
  requestType: 'json', // default

  // ’parseResponse‘ 是否对请求返回的 Response 对象做格式、状态码解析
  parseResponse: true, // default

  // ’charset‘ 当服务端返回的数据编码类型为 gbk 时可使用该参数,会按 gbk 编码做解析,避免得到乱码, 默认为 utf8
  // 当 parseResponse 值为 false 时该参数无效
  charset: 'utf-8',

  // 'responseType': 如何解析返回的数据,当 parseResponse 值为 false 时该参数无效
  // 默认为 'json', 对返回结果进行 Response.text().then( d => JSON.parse(d) ) 解析
  // 其他(text, blob, arrayBuffer, formData), 做 Response[responseType]() 解析
  responseType: 'json', // default

  // 'throwErrIfParseFail': 当 responseType 为 json 但 JSON.parse(data) fail 时,是否抛出异常。默认不抛出异常而返回 Response.text() 后的结果,如需要抛出异常,可设置 throwErrIfParseFail 为 true
  throwErrIfParseFail: false, // default

  // 'getResponse': 是否获取源 Response, 返回结果将包含一层: { data, response }
  getResponse: false,// default

  // 'errorHandler' 统一的异常处理,供开发者对请求发生的异常做统一处理,详细使用请参考下方的错误处理文档
  errorHandler: function(error) { /* 异常处理 */ },

  // 'cancelToken' 取消请求的 Token,详细使用请参考下方取消请求文档
  cancelToken: null,
}

响应结构

某个请求的响应返回的响应对象 Response 如下:

{
  // `data` 由服务器提供的响应, 需要进行解析才能获取
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},
}

当 options.getResponse === false 时, 响应结构为解析后的 data

BSFetch.get('/api/v1/xxx', { getResponse: false })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.log(error);
  });

当 options.getResponse === true 时,响应结构为包含 data 和 Response 的对象

BSFetch.get('/api/v1/xxx', { getResponse: true })
  .then(({ data, response })=> {
    console.log(data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
  })

在使用 catch 或者 errorHandler, 响应对象可以通过 error 对象获取使用,参考错误处理这一节文档。

错误处理

import BSFetch, { create } from '@beisen/fetch';

const errorHandler = function (error) {
  const codeMap = {
    '401': '发生错误啦',
    '022': '发生大大大大错误啦',
    // ....
  };
  if (error.response) {
    // 请求已发送但服务端返回状态码非 2xx 的响应
    console.log(error.response.status);
    console.log(error.response.headers);
    console.log(error.data);
    console.log(error.request);
    console.log(codeMap[error.data.status])

  } else {
    // 请求初始化时出错或者没有响应返回的异常
    console.log(error.message);
  }

  throw error;   // 如果throw. 错误将继续抛出.

  // 如果return, 则将值作为返回. 'return;' 相当于return undefined, 在处理结果时判断response是否有值即可.
  // return {some: 'data'};
}

// 1. 作为统一错误处理
const extendBSFetch = create({ errorHandler });

// 2. 单独特殊处理, 如果配置了统一处理, 但某个api需要特殊处理. 则在请求时, 将errorHandler作为参数传入.
BSFetch('/api/v1/xxx', { errorHandler });


// 3. 通过 Promise.catch 做错误处理
BSFetch('/api/v1/xxx')

  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    return errorHandler(error);
  });

拦截器

在请求或响应被 thencatch 处理前拦截它们。

// request拦截器, 改变url 或 options.
BSFetch.interceptors.request.use((url, options) => {
  return (
    {
      url: `${url}&interceptors=yes`,
      options: { ...options, interceptors: true },
    }
  );
});

// response拦截器, 处理response
BSFetch.interceptors.response.use((response, options) => {
  response.headers.append('interceptors', 'yes yo');
  return response;
});

// 提前对响应做异常处理
BSFetch.interceptors.response.use((response) => {
  const codeMaps = {
    502: '网关错误。',
    503: '服务不可用,服务器暂时过载或维护。',
    504: '网关超时。',
  };
  message.error(codeMaps[response.status]);
  return response;
});

// 克隆响应对象做解析处理
BSFetch.interceptors.response.use(async (response) => {
  const data = await response.clone().json();
  if(data && data.NOT_LOGIN) {
    location.href = '登录url';
  }
  return response;
})

取消请求

你可以通过 cancel token 来取消一个请求

cancel token API 是基于已被撤销的 cancelable-promises 方案

  1. 你可以通过 CancelToken.source 来创建一个 cancel token,如下所示:
import BSFetch from '@beisen/fetch';

const CancelToken = BSFetch.CancelToken;
const { token, cancel } = CancelToken.source();

BSFetch.get('/api/cancel', {
  cancelToken: token
}).catch((thrown)=>{
  if (BSFetch.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理异常
  }
});

BSFetch.post('/api/cancel', {
  name: 'hello world'
}, {
  cancelToken: token
})

// 取消请求(参数为非必填)
cancel('Operation canceled by the user.');
  1. 你也可以通过实例化 CancelToken 来创建一个 token,同时通过传入函数来获取取消方法:
import BSFetch from '@beisen/fetch';

const CancelToken = BSFetch.CancelToken;
let cancel;

BSFetch.get('/api/cancel', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
});
// 取消请求
cancel();

案例

文件上传

使用 FormData() 构造函数时,浏览器会自动识别并添加请求头 "Content-Type: multipart/form-data", 且参数依旧是表单提交时那种键值对,因此不需要开发者手动设置 Content-Type

const formData = new FormData();
formData.append('file', file);
BSFetch('/api/v1/some/api', { method:'post', data: formData });