valor-request

1.1.9 • Public • Published

valor-request

基于umi-request的开箱即用的request

用法示例

示例 1: 后端返回标准的 Result 结构

如果后端返回的格式如下( response.status 总是返回 200 ) :

// 返回的httpCode===200!
interface Result<T = any> {
  // 由于response.httpStatus=200, 这里放实际的httpStatus
  code: number; //200| 201| 400 | 404 | 403

  // 所有有效数据将保存到这里, 比如分页信息应存为: {data: {meta: ..., data:[...]}}
  data?: T; // {user: [1,2]}

  // 不同于code, 这是业务Code, 比如'ProductionNotExists', 然后前端查取 错误描述
  // 然而: 多数程序直接返回 errorMsg, 所以实际上用不到errorCode

  errorCode?: string;

  errorMsg?: string; // 仅code不为200/201时生效
}

比如在nodejs时这样写:

正常:
response.send({code: 200, data: {users: [1]}}});
错误: 用msg表示错误
response.send({code: 404, errorMsg: '页面不存在'});

那么前端配置非常简单:

// rpc.ts
import getRequest from 'valor-request';
export default getRequest({
  prefix: 'http://localhost:3001/api',
})

使用时:

import request from './rpc';
function getUsers() {
  return request('/users');
}

示例 2: 后端用 http status 表示成功与失败

由于返回格式与Result格式不兼容, 需要进行转换(normalize):
后端返回:

正常: 用data表示数据
response.send({data: {users: [1]}}});
错误: 用msg表示错误
response.status(404).send({msg: '页面不存在'});

前端配置:

// rpc.ts
import getRequest from 'valor-request';
export default getRequest({
  prefix: 'http://localhost:3001/api',
  normalize: (result:any)  => ({
    code: 200,   <== 统一设为200
    data: result.data,
    errorMsg: result.msg
  })
})

使用:

import request from './getRequest';
function getUsers() {
  return request('/users');
}

示例 3: 后端返回的 http status 永远为 200, 用 result.code 表示成功与失败

此种情形与valor-request假设一致, 但可能字段名称与Result不匹配, 同样需要进行转换(normalize):
后端返回:

正常:
response.send({xcode: 200, xdata: {users: [1]}}});
错误: 用msg表示错误
response.send({xcode: 200, xmsg: '页面不存在'});

前端配置:

// rpc.ts
import getRequest from 'valor-request';
export default getRequest({
  prefix: 'http://localhost:3001/api',
  normalize: (result:any)  => ({
    code: result.xcode,   <== 统一设为200
    data: result.xdata,
    errorMsg: result.xmsg
  })
})

示例 4: 添加错误处理与 loading 状态

前端配置:

// rpc.ts
import getRequest from 'valor-request';
import uiStore from './UIStore';
export default getRequest({
  prefix: 'http://localhost:3001/api',
  onError: (e) => uiStore.addMsg(e.errorMsg),
  beforeRequest: () => uiStore.setLoading(true),
  afterRequest: () => uiStore.setLoading(false)
})

示例 5: 配置写 token 的方法

默认写入headers: {Authorization: Bearer ${token}}
默认tokenlocalStorage.getItem('token')读取
如果跟实际情况不一致, 请使用如下方式覆盖:

import getRequest from 'valor-request';
export default getRequest({
  setToken() {
    const token = localStorage.getItem('jwttoken');
    return {token};
  }
})

动机

每个项目, 总是要造一个request轮子
无论你使用axios, 还是最简单的fetch, 或是umi-request, 你总得考虑以下问题:

  • token如何整合
  • 如何处理错误处理, 错误是留到上层处理, 还是底层处理
  • loading状态要在底层处理, 还是由调用者自行处理
  • 后台应该返回status状态码, 还是全部返回200+error-data
  • 如何将后台返回的数据结构, 与你的前台数据结构进行对应

进一步, 你可能还得考虑:

  • 超时
  • 缓存(对报表型的应用尤其重要)

所以干脆再造一个轮子, 目的是上手即用

特性

实际上, valor-request是一个统一的(微型)请求框架:

  • 自动整合tokenrequest.header
  • 转换器: 实现前后台数据结构对应.
  • 全局错误处理
  • 请求生命周期 hook, 方便实现自己的 loading 状态管理
  • 可设置请求超时
  • 可实现GET型请求缓存

底层

基于umi-request
其实底层是什么都不重要, 选umi-request的原因是: 小而全(详见其官网对照表)\

用法

  1. yarn add valor-request
  2. 配置: 见下面的描述
  3. 使用: 见上面的例子

基本配置

import getRequest from 'valor-request';
getRequest({
  // 在ajax型请求前面加上/api前缀
  prefix: '/api',
  // 显示loading状态
  beforeRequest: () => uiStore.showLoading(true),
  afterResponse: () => uiStore.showLoading(false),
  // 显示错误
  onError: (e) => uiStore.addError(e)
});
export default request;

注意如下的精简配置, 必须满足以下条件:

  1. token来自`localStorage.getItem('token'),
  2. token将保存为request.header['Authorization']='Bearer ${token}'
  3. 后台返回数据结构:
type Result<T> {
  code: 200 | 403 | 404 |...;
  data?: T;
  errorMsg?: string;
}

这是目前比较通用的结构, 特点是:

  • response.status总是200
  • 错误码写在result.code
  • 一旦发生错误, 则dataundefined, errorMsg是中文错误信息
  • 字段级错误可以通过将 json 字符串写在errorMsg里解决
  • 不太符合 http 标准, 但在国内最常用
  1. 请求超时10秒
  2. cache

Result 转换

getRequest({
  normalize: (后台返回的result格式) => Result
})

参见前面的例子.
总之, 你得保证最后得到的Result刚好是valor-request的标准Result

错误处理

getRequest({
  onError(error:Result) => ...
})

注意这里收到的error, 是已转化为Result格式的!\

超时

getRequest({
  timeout: 5000
})

开启缓存

getRequest({
  cache: {max/*最多缓存记录*/, ttl/*缓存超时*/}
})

覆盖其它继承自umi-request的配置项

暂时只能一次性覆盖, 直到找到需要永久覆盖的场景:

import request from './rpc';
request(umi-request配置项).then(...)

Readme

Keywords

none

Package Sidebar

Install

npm i valor-request

Weekly Downloads

1

Version

1.1.9

License

MIT

Unpacked Size

17.9 kB

Total Files

5

Last publish

Collaborators

  • g770728y