puta

1.2.4 • Public • Published

puta

基于 axios , 但添加了许多有用的功能.

安装

$ npm install puta

使用

得到实例

import Puta form 'puta';
 
// 或
let puta = Puta({
  baseURL: xxx,
  timeout: 12000
});
 
let puta = new Puta({
  baseURL: xxx,
  timeout: 12000
});
 
 
 

进行请求:

puta.get('/user', {ID: '12345'})
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
  
puta.post('/user', {ID: '12345'})
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
 

注册模块化的请求路径,

非必须, 详情查看下面文档 api .moduleRegister()为什么使用模块注册 的章节:

import Puta form 'puta';
 
let puta = Puta();
 
// 注册一个 menu 的路径模块
puta.moduleRegister({
  a: '/app',
  b: '/init.js',
}, 'menu')
 
// 注册一个  home 的路径模
// 路径除了是字符串, 还可以是对象 
puta.moduleRegister({
  c: '/app',
  d: {
    path: '/init.js',
    reqData: (data)=>{
 
      // 在 data 传递给请求之前, 可以处理下 data
      // 必须返回数据
 
      return data
    },
    use: (response)=>{
      
      // 在响应后, 可以处理下响应数据
      // 必须返回 数据
 
      return response
    },
    config: {} // puta config
  },
}, 'home')
 
 
// 然后你可以像下面这样请求
 
// mApis 保存着模块的命名空间
// 例如上面我们注册的 home 和 menu
puta.mApis.home.a(...rest) // get 请求
// 等价于 puta.get('/app', ...rest)
 
puta.mApis.home.a.post(...rest) //post
// 等价于 puta.post('/app', ...rest)
 
// apis 可以直接访问路径名, 无需加上模块名, 但需要警惕命名污染
puta.apis.a.post() //post
puta.apis.d.get() //此处 get可以省略
 

API

new Puta([config]) or puta([config])

config

Type: object

此 config 我们把它叫做 puta 的 config.

在不同阶段都可以传入 config 配置用于规划请求相关的行为, 详情查看: config 的层级覆盖

除了下面选项之外, 还可以参见: axios request-config

{
  stringfieldData: false, //  默认 false , 是否开启对 post 请求参数进行字符串化
 
  use: ()=>{}, // 一个函数, 对响应进行一次 use, 类似 axios.interceptors.response.use
 
  cancelUse: boolean, //是否取消 use, 在某些场景会用到
  
  cancel: object|function// 取消请求用
  
}
stringfieldData

Type: boolean

是否对 post 请求的 request data 进行字符串序列化成 application/x-www-form-urlencoded 数据格式.

细节参见: 🐔🐔关于 post和 stringfieldData 配置项的关系

use

Type: function

类似传给axios.interceptors.response.use(fn)的第一个参数 fn, 此处的 use 函数会后于 axios.interceptors.response.use 执行.

cancelUse

取消 config 中 use 函数的执行.

更多信息查看: 为什么要在 config 中同时出现 use和 cancelUse

cancel

取消请求.

更多请查看: 如何取消请求

实例属性

.mApis

type: Proxy 调用 .moduleRegister() 后, 通过所注册的 api 路径的命名空间访问路径名;

如:

// 假如注册了两个模块, x 和 y
puta.moduleRegister({
  p1: '/ffds',
  p2: '/xxx',
},x)
puta.moduleRegister({
  p3: '/for_p3',
  p4: '/for_p4',
},y)
 
// 则可以通过如下方式访问相关路径来进行请求:
// 访问 p1,p2
puta.mApis.x.p1.post()
puta.mApis.x.p2.post()
// 访问 p3,p4
puta.mApis.y.p3.post()
puta.mApis.y.p3.post()
 
 
 

.apis

type: Proxy 调用 .moduleRegister() 后, 可以不通过命名空间直接访问路径名 如:

// 假如注册了两个模块, x 和 y
puta.moduleRegister({
  p1: '/ffds',
  p2: '/xxx',
  p5: '/for_x'
},x)
puta.moduleRegister({
  p3: '/for_p3',
  p4: '/for_p4',
  p5: '/for_y'
},y)
 
// 则可以通过如下方式访问相关路径来进行请求:
// 访问 p1,p2
puta.apis.p1.post()
puta.apis.p2.post()
// 访问 p3,p4
puta.apis.p3.post()
puta.apis.p3.post()
 
// 但要注意, p5在两个模块都有, 此时需要通过模块来访问路径
puta.mApis.x.p5.post()
puta.mApis.y.p5.post()
 
 

注意: 如果有两个以上的路径命名空间(模块)拥有同一个路径名, 但要警惕命名污染, 可能会产生非预期的结果.

实例方法

动词请求相关方法

.get(url [, params [, config]])
.delete(url [, params [, config]])
.head(url [, params [, config]])
.options(url [, params [, config]])
.post(url [,data, [,stringified] [,config]])
.put(url [,data, [,config]])
.patch(url [,data, [,config]])

如果通过已经注册了 api 模块, 则使用动词方法时可以省略第一个参数: url

  • config: puta 的 config
  • params: 传递的请求参数
  • data: 传递的请求参数
  • stringified: boolean, 类似 querystring.stringify() 一样序化请求体 . 你也可以传递一个对象, 这个时候就会被当做 config 来对待. 而 stringified 的值由 puta.options.stringfieldData 来决定

.all(Array<Promise>)

同 axios.all()

.setDefaults(callback)

callback 函数接收一个参数: axios实例的 defaults 属性, 可以在此修改一下默认 config, 这会覆盖 实例化 puta 时传入的 config

.reqUse(...args)

同 of axios.interceptors.request.use

.resUse(...args)

同 of axios.interceptors.response.use

.moduleRegister(apis, name, config)(重要) 🍠🍠🍠

更多细节查看: 为什么使用模块注册.

参数说明:

  • apis: 路径模块, type: object
  • name: 模块的命名空间, type: string
  • config: 这个模块的所有请求都会结合这个 config, puta的 config

关于 apis: 参数 : type: object

{
  // path 的值可以是字符串或对象
  path1: '',  // 值是一个字符串
  path2: { // 值是一个对象
    path: '', //required
    reqData: data=>data, // optional
    use: response=>response, //optional
    config: {}, //optional
  }
}
  • reqData 函数可以在 dataparams 传递给请求之前进行一些处理, 必须返回一个处理后的 data

  • use 函数可以在响应数据返回之后立即进行一些处理, 必须返回一个处理后响应数据.

  • config: puta 的 config , 只对 此请求路径有效

注册后模块后, 可以使用如下方式进行请求:

puta.apis.[method](...res)puta.mApis.[moduleName].[method]()

  • method 就是 get, post, head... 等动词请求方法.
  • moduleName 就是 moduleRegister 的第二个参数
  • ...rest : 就是参数列表, 其参数列表就是动词方法除去第一个参数:url 后剩余的参数别表, 比如
    • get: puta.apis.[method].get(params, config)
    • post: puta.apis.[method].post(data,[stringfield], config)

查看以下实例(为简化, 部分使用了伪代码), 注意阅读注释部分:

// 实例
let puta = Puta({
  baseURL: 'http://aaa.com'
});
 
let apis = puta.apis;
 
// 注册一个模块
// 处于演示需要, path的值我们故意使用两种形式, 字符串或对象
puta.moduleRegister({
  useInfo: '/user',
  goodsList: {
    path: '/goods',
    // reqData 是可选字
    reqData:data=>{
      data.addP = 'add'
      return data
    },
    // use 是可选字段
    use: res=>{
      res.x = 5;
      return x;
    }
    // config 是可选字段
    config: {
      baseURL: 'http://bbb.com'
    }
  },
}, home)
 
 
 
// 如果我们此时请求的路径是 goods:
// 请求的最终 url 本来是: 'http://aaa.com/goods', 但因为 config的配置,
// 变成了: 'http://bbb.com/goods'
apis.goodsList.get({
  mob: 'yesternight'
},{baseURL: 'http://mob.com', timeout: 1600})
  .then(res=>{
    // res 会先流过 use, 变成
    // {
    //   x:5,
    //   ...otherData
    // }
    console.log(res, '看看 res是什么')
 
  })
 
// {mob: 'yesternight'} 会流过 reqData, 变成
// {mob: 'yesternight', addP: 'add'}
 
// 事实上, 以上行为和以下行为是等价的: 
 
// request data 的处理环节
let data = (data=>{
  data.addP = 'add'
  return data
})({
  mob: 'yesternight'
})
 
// config 的覆盖情况
let config = Object.assign(
  {},
  {baseURL: 'http://aaa.com'},
  {baseURL: 'http://bbb.com'},
  {baseURL: 'http://mob.com', timeout: 1600}
)
 
puta.get('/goods', data, config)
.then(res=>{ // res 先被 use 处理
  res.x = 5;
  return x;
})
.then(res=>{
  console.log(res, '看看 res是什么')
})
 

🐔🐔config 的层级覆盖

如果直接使用动词请求, config 会出现在 2 个层级:

  1. 新建实例时: Puta( [config] )
  2. 请求时, puta.get(params, [config] )

如果注册api 模块, 并通过模块路径访问请求: 那么 config 会出现在3 或 4 个层级:

  1. 新建实例时: Puta( [config] )
  2. 注册模块时: .moduleRegister(apis, name, [config] )
  3. api路径配置为对象时: apis = {a: {config: [config] }}
  4. 请求时: apis.a.get(params, [config] )

如果把 1,2,3,4 比喻为配置出现在的层级, 有两个或以上的地方出现 config 的时候, 相同的属性会出现覆盖,

高层级覆盖低层级的属性, 比如: 4 层级的会覆盖,3 层级的, 3 层级的会覆盖 2 层级的, 依次类推

🐔🐔如何取消请求

你可以完全使用 axios 的取消请求的方式来进行取消请求的功能.

点击这里进行比较: axios cancel

但是 puta 也提供了另一种方式, 相比 axios 的方式更简洁.

可以像下面这样 使用puta.cancel() 创建一个取消函数, 查看如下代码:

let puta = Puta();
 
let cancel = puta.cancel();
 
puta.get('/user/12345', {
  cancel
}).catch(function (err) {
  if (err.isCancel) {
    console.log('Request canceled', thrown.message);
  } else {
    // handle error
  }
});
 
axios.post('/user/12345', {
  name: 'new name'
}, {
  cancel
})
 
// 取消请求 ( message 参数是可选的)
cancel('用户取消了请求');
 

也可以不使用 puta.cancel(), 而是给一个空对象:

let puta = Puta();
 
let cancel = {}
 
puta.get('/user/12345', {
  cancel
});
 
// 取消请求
cancel.cancel('请求被取消')
 

两种方式的异同, 相对来说第二种方式更加简洁, 但是需要提前取消请求只能使用第一中:

let puta = Puta();
 
let cancel1 = puta.cancel();
 
// 在 cancel1 函数传递给 config 之前就可以提前取消
cancel1('我被提前取消了');
 
puta.get('/user/12345', {
  cancel: cancel1
})
 
 
// =====================
 
 
let cancel2 = {};
 
puta.get('/user/12345', {
  cancel: cancel2
})
 
cancel.cancel('我只能被传递给 config 之后才能取消')
 

🐔🐔关于 post和 stringfieldData 配置项的关系

在 axios 中, 提供了如何得到 application/x-www-form-urlencoded 数据格式的 方案.

这可能会引入一个额外的 qs 库来序列化字符串, 这类序列化的库实现了完整的序列化标准, 功能强大, 对于复杂的数据收发标准会很有用.

但是对于一些简单的数据收发标准(项目的大多数情况都是简单的), puta 提供了更轻量化的方案.

此方案只在 post 请求生效, 我们先看看 post 请求的函数格式:

puta.post(url [, data [,stringfield] [, config]] )

第三参数是可选的, 可以是 bool 值, 也可以省略或是个对象.

  • 如果是布尔值, 则代表含义是 stringfield 的值
  • 如果是个对象, 则代表的函数是 config 对象

stringfield 设置为 true 就会对 data 进行序列化处理:

let puta = Puta()
 
puta.post('/abc', {name: 'bob'}, true)
// 或者在 config 中进行配置
puta.post('/abc', {name: 'bob'}, {
  stringfieldData: true
})
// 以上两种方式是等价的
 

以上两种方式是等价的, 这意味着可以利用 config 的层次覆盖来得到 是否进行进行 stringfield, 查看如下代码:

// 在第一层级的 config 中设置
let puta = Puta({
  stringfieldData: true
})
// 此时数据会被格式化
puta.post('/abc', {name: 'bob'})
 
// 如果注册了api模块, 并且没设置 stringfieldDdata, 
// 此时由于层级覆盖的关系, 数据也会被格式化
// 下面这行是伪代码
puta.apis.a.post({name: 'bob'})
 
// 在更高层级设置 false 可以阻止格式
puta.post('/abc', {name: 'bob'}, false)
puta.apis.a.post({name: 'bob'}, false)
 
==========================
 
// 在 2 或 3 层级进行数据格式化
// 以在第二层为例
puta.moduleRegistery({cs: '/abc'}, 'x', {
  stringfieldData: true
})
 
// 此时数据也会被格式化
puta.apis.cs.post({name: 'bob'})
 
// 在更高层级设置 false 可以阻止格式
puta.apis.cs.post({name: 'bob'}, false)
 

res use 的执行顺序

req use 的执行顺序

关于缓存

🐔🐔 为什么使用模块注册

🐔🐔 为什么要在 config 中同时出现 use和 cancelUse

  • moduleRegister 第二个参数默认值为 default
  • puta 有初始实例化
  • 实例化隔开的缓存

Readme

Keywords

Package Sidebar

Install

npm i puta

Weekly Downloads

2

Version

1.2.4

License

MIT

Unpacked Size

58.6 kB

Total Files

17

Last publish

Collaborators

  • flowke