目录

🌓 实现请求和响应配置化

# 需求分析

aixos 库中,默认配置会添加 transformRequesttransformResponse 两个字段,它们的值是一个数组或者是一个函数。

  • transformRequest :允许将请求数据发送到服务器之前进行修改,适用于 putpostpatch 请求方法,如果值是数组,则数组中的最后一个函数必须返回一个字符串 FormDataURLSearchParamsBlob 等类型作为 xhr.send 方法的参数,而且在 transform 过程中可以修改 headers 对象;
  • transfromResponse 允许在相应数据传递给 then 或者 catch 之前对它们进行修改;当值为数组的时候,数组的每个函数都是一个转换函数,前者的输出作为后者的输入。

🌰 例子:

axios({
  transfromRequest: [(function(data) {
    return qs.stringify(data)
  }), ...axios.defaults.transformRequest],
	transformResponse: [axios.defaults.transformResponse, function(data) {
    if(typeof data === 'object') {
      data.b = 2
    }
    return data
  }],
  url: '/config/post',
  method: 'post',
  data: {
    a: 1
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 修改默认配置

src/types/index.ts 中:

添加一个类型 AxiosTransformer

export interface AxiosTransformer {
  (data: any, headers?: any):any
}
1
2
3

然后修改 AxiosRequestConfig 的类型定义:

export interface AxiosRequestConfig {
  // ...
  transformRequest?: AxiosTransformer | AxiosTransformer[]
  transformResponse?: AxiosTransformer | AxiosTransformer[]
}
1
2
3
4
5

添加两个可选属性。

然后修改默认配置,在 src/defaults.ts 中:

import { AxiosRequestConfig } from './types'
import { processHeaders } from './helpers/headers'
import { transformRequest, transformResponse } from './helpers/data'

const defaults: AxiosRequestConfig = {
  method: 'get',
  timeout: 0,
  headers: {
    common: {
      Accept: 'application/json, text/plain, */*'
    }
  },

  transformRequest: [
    function(data: any, headers: any): any {
      processHeaders(headers, data)
      return transformRequest(data)
    }
  ],
  transformResponse: [
    function(data: any): any {
      return transformResponse(data)
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

将之前对请求数据和相应数据的处理逻辑,放到默认配置中。

# transform 逻辑重构

重构之前写的 对请求数据和相应数据的处理逻辑。可能会编写多个转换函数,先定义一个 transform 函数处理这些转换函数的调用逻辑。

src/core/transform.ts

import { AxiosTransformer } from '../types'

export default function transform(
  data: any,
  headers: any,
  fns?: AxiosTransformer | AxiosTransformer[]
): any {
  if(!fns) return data
  
  if(!Array.isArray(fns)) fns = [fns]
  
  fns.forEach(fn => {
    data = fn(data, headers)
  })
  
  return data
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

transform 函数中接收三个参数,其中 fns 代表一个或者多个转换函数,内部逻辑为 遍历 fns ,执行这些转换函数,并且把 dataheaders 作为参数传入,每个转换函数返回的 data 或作为下一个转换函数的参数 data 传入。

修改对请求数据和相应数据处理的逻辑:

src/core/dispatchRequest.ts

function processConfig(config: AxiosRequestConfig): void {
  config.url = transformURL(config)
  config.headers = transformRequestHeader(config)
  config.data = transform(config.data, config.headers, config.transformRequest)
  config.headers = flattenHeaders(config.headers, config.method!)
}
1
2
3
4
5
6
function transformResponseData(res: AxiosResponse): AxiosResponse {
  res.data = transform(res.data, res.headers, res.config.transformResponse)
  return res
}
1
2
3
4

将对请求数据的处理和对响应数据的处理改成适用 transform 函数的实现,并且把配置中的 transformRequest 以及 transformResponse 分别传入。

# 编写测试 DEMO

axios({
  transfromRequest: [(function(data) {
    return qs.stringify(data)
  }), ...axios.defaults.transformRequest],
	transformResponse: [axios.defaults.transformResponse, function(data) {
    if(typeof data === 'object') {
      data.b = 2
    }
    return data
  }],
  url: '/config/post',
  method: 'post',
  data: {
    a: 1
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
📢 上次更新: 2022/09/02, 10:18:16