Will's blog Will's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • VUE
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

will

前端小学生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • VUE
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 初识 TypeScript

  • TypeScript 常用语法

  • ts-axios 项目初始化

  • ts-axios 基础功能实现

  • ts-axios 异常情况处理

  • ts-axios 接口扩展

  • ts-axios 拦截器实现

  • ts-axios 配置化实现

  • ts-axios 取消功能实现

  • ts-axios 更多功能实现

    • withCredentials
    • XSRF 防御
    • 上传和下载的进度监控
    • HTTP 授权
    • 自定义合法状态码
    • 自定义参数序列化
      • 需求分析
      • 代码实现
      • demo 编写
    • baseURL
    • 静态方法扩展
  • ts-axios 单元测试

  • ts-axios 部署与发布

  • 《TypeScript 从零实现 axios》
  • ts-axios 更多功能实现
HuangYi
2020-01-05
目录

自定义参数序列化

# 自定义参数序列化

# 需求分析

在之前的章节,我们对请求的 url 参数做了处理,我们会解析传入的 params 对象,根据一定的规则把它解析成字符串,然后添加在 url 后面。在解析的过程中,我们会对字符串 encode,但是对于一些特殊字符比如 @、+ 等却不转义,这是 axios 库的默认解析规则。当然,我们也希望自己定义解析规则,于是我们希望 ts-axios 能在请求配置中允许我们配置一个 paramsSerializer 函数来自定义参数的解析规则,该函数接受 params 参数,返回值作为解析后的结果,如下:

axios.get('/more/get', {

  params: {

    a: 1,

    b: 2,

    c: ['a', 'b', 'c']

  },

  paramsSerializer(params) {

    return qs.stringify(params, { arrayFormat: 'brackets' })

  }

}).then(res => {

  console.log(res)

})

1
2
3
4
5
6
7
8
9
10
11
12

# 代码实现

首先修改一下类型定义。

types/index.ts:

export interface AxiosRequestConfig {

  // ...

  paramsSerializer?: (params: any) => string

}

1
2
3
4

然后修改 buildURL 函数的实现。

helpers/url.ts:

export function buildURL(

  url: string,

  params?: any,

  paramsSerializer?: (params: any) => string

): string {

  if (!params) {

    return url

  }



  let serializedParams



  if (paramsSerializer) {

    serializedParams = paramsSerializer(params)

  } else if (isURLSearchParams(params)) {

    serializedParams = params.toString()

  } else {

    const parts: string[] = []



    Object.keys(params).forEach(key => {

      const val = params[key]

      if (val === null || typeof val === 'undefined') {

        return

      }

      let values = []

      if (Array.isArray(val)) {

        values = val

        key += '[]'

      } else {

        values = [val]

      }

      values.forEach(val => {

        if (isDate(val)) {

          val = val.toISOString()

        } else if (isPlainObject(val)) {

          val = JSON.stringify(val)

        }

        parts.push(`${encode(key)}=${encode(val)}`)

      })

    })



    serializedParams = parts.join('&')

  }



  if (serializedParams) {

    const markIndex = url.indexOf('#')

    if (markIndex !== -1) {

      url = url.slice(0, markIndex)

    }



    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams

  }



  return url

}

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

这里我们给 buildURL 函数新增了 paramsSerializer 可选参数,另外我们还新增了对 params 类型判断,如果它是一个 URLSearchParams 对象实例的话,我们直接返回它 toString 后的结果。

helpers/util.ts:

export function isURLSearchParams(val: any): val is URLSearchParams {

  return typeof val !== 'undefined' && val instanceof URLSearchParams

}

1
2
3

最后我们要修改 buildURL 调用的逻辑。

core/dispatchRequest.ts:

function transformURL(config: AxiosRequestConfig): string {

  const { url, params, paramsSerializer } = config

  return buildURL(url!, params, paramsSerializer)

}

1
2
3
4

# demo 编写

axios.get('/more/get', {

  params: new URLSearchParams('a=b&c=d')

}).then(res => {

  console.log(res)

})



axios.get('/more/get', {

  params: {

    a: 1,

    b: 2,

    c: ['a', 'b', 'c']

  }

}).then(res => {

  console.log(res)

})



const instance = axios.create({

  paramsSerializer(params) {

    return qs.stringify(params, { arrayFormat: 'brackets' })

  }

})



instance.get('/more/get', {

  params: {

    a: 1,

    b: 2,

    c: ['a', 'b', 'c']

  }

}).then(res => {

  console.log(res)

})

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
26
27
28
29
30
31

我们编写了 3 种情况的请求,第一种满足请求的 params 参数是 URLSearchParams 对象类型的。后两种请求的结果主要区别在于前者并没有对 [] 转义,而后者会转义。

至此,ts-axios 实现了自定义参数序列化功能,用户可以配置 paramsSerializer 自定义参数序列化规则。下一节课我们来实现 ts-axios 对 baseURL 的支持。

编辑此页 (opens new window)
#TypeScript
上次更新: 2024/08/22, 14:42:43
自定义合法状态码
baseURL

← 自定义合法状态码 baseURL→

最近更新
01
我用AI写前端代码这一年:从怀疑到真香的转变
09-15
02
基于 Next.js 的无人机数据孪生可视化平台实践
07-17
03
vite 包缓存问题 处理
06-04
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Will | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式