@beisen/fetch
TypeScript icon, indicating that this package has built-in type declarations

2.0.2 • Public • Published

@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 });

Readme

Keywords

none

Package Sidebar

Install

npm i @beisen/fetch

Weekly Downloads

2

Version

2.0.2

License

MIT

Unpacked Size

97.8 kB

Total Files

6

Last publish

Collaborators

  • albert-zhang
  • beisencorp
  • lgm
  • liugenpeng
  • neozw