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 授权
    • 自定义合法状态码
    • 自定义参数序列化
    • baseURL
    • 静态方法扩展
      • 需求分析
      • 代码实现
      • demo 编写
  • ts-axios 单元测试

  • ts-axios 部署与发布

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

静态方法扩展

# 静态方法扩展

# 需求分析

官方 axios 库实现了 axios.all、axios.spread 等方法,它们的用法如下:

function getUserAccount() {

  return axios.get('/user/12345');

}



function getUserPermissions() {

  return axios.get('/user/12345/permissions');

}



axios.all([getUserAccount(), getUserPermissions()])

  .then(axios.spread(function (acct, perms) {

    // Both requests are now complete

  }));

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

实际上,axios.all 就是 Promise.all 的封装,它返回的是一个 Promise 数组,then 函数的参数本应是一个参数为 Promise resolves(数组)的函数,在这里使用了 axios.spread 方法。所以 axios.spread 方法是接收一个函数,返回一个新的函数,新函数的结构满足 then 函数的参数结构。

个人认为 axios 这俩静态方法在目前看来很鸡肋,因为使用 Promise 一样可以完成这俩需求。

function getUserAccount() {

  return axios.get('/user/12345');

}



function getUserPermissions() {

  return axios.get('/user/12345/permissions');

}



Promise.all([getUserAccount(), getUserPermissions()])

  .then(([acct,perms]) {

    // Both requests are now complete

  }));

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

在 Promise.all 的 resolve 函数中,我们可以直接通过数组的解构拿到每个请求对应的响应对象。

但是为了保持与官网 axios API 一致,我们也在 ts-axios 库中实现这俩方法。

官方 axios 库也通过 axios.Axios 对外暴露了 Axios 类(感觉也没有啥使用场景,但为了保持一致,我们也会实现)。

另外对于 axios 实例,官网还提供了 getUri 方法在不发送请求的前提下根据传入的配置返回一个 url,如下:

const fakeConfig = {

  baseURL: 'https://www.baidu.com/',

  url: '/user/12345',

  params: {

    idClient: 1,

    idTest: 2,

    testString: 'thisIsATest'

  }

}

console.log(axios.getUri(fakeConfig))

// https://www.baidu.com/user/12345?idClient=1&idTest=2&testString=thisIsATest

1
2
3
4
5
6
7
8
9
10
11

# 代码实现

首先修改类型定义。

types/index.ts:

export interface AxiosClassStatic {

  new (config: AxiosRequestConfig): Axios

}



export interface AxiosStatic extends AxiosInstance {

  // ...



  all<T>(promises: Array<T | Promise<T>>): Promise<T[]>



  spread<T, R>(callback: (...args: T[]) => R): (arr: T[]) => R



  Axios: AxiosClassStatic

}



export interface Axios {

  // ...



  getUri(config?: AxiosRequestConfig): string

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

然后我们去实现这几个静态方法。

axios.ts:

axios.all = function all(promises) {

  return Promise.all(promises)

}



axios.spread = function spread(callback) {

  return function wrap(arr) {

    return callback.apply(null, arr)

  }

}



axios.Axios = Axios

1
2
3
4
5
6
7
8
9
10
11

最后我们去给 Axios 添加实例方法 getUri。

core/Axios.ts:

getUri(config?: AxiosRequestConfig): string {

  config = mergeConfig(this.defaults, config)

  return transformURL(config)

}

1
2
3
4

先和默认配置合并,然后再通过 dispatchRequest 中实现的 transformURL 返回一个新的 url。

# demo 编写

function getA() {

  return axios.get('/more/A')

}



function getB() {

  return axios.get('/more/B')

}



axios.all([getA(), getB()])

  .then(axios.spread(function(resA, resB) {

    console.log(resA.data)

    console.log(resB.data)

  }))





axios.all([getA(), getB()])

  .then(([resA, resB]) => {

    console.log(resA.data)

    console.log(resB.data)

  })



const fakeConfig = {

  baseURL: 'https://www.baidu.com/',

  url: '/user/12345',

  params: {

    idClient: 1,

    idTest: 2,

    testString: 'thisIsATest'

  }

}

console.log(axios.getUri(fakeConfig))

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

这里我们通过 axios.all 同时发出了 2 个请求,返回了 Promise 数组,,我们可以在 axios.spread 的参数函数中拿到结果,也可以直接在 then 函数的参数函数中拿到结果。另外,我们可以根据 axios.getUri 方法在不发送请求的情况下根据配置得到最终请求的 url 结果。

至此,ts-axios 就实现了官网 axios 库在浏览器端的所有需求。如果你学到了这里,先为自己鼓个掌吧,因为我们已经获得了阶段性的学习成果了。

目前为止,我们对于所写代码的验证都是通过 demo 的方式,但是 demo 毕竟难以覆盖所有场景和代码分支,为了保证代码的正确性,我们还需要更科学的方式。从下一章开始,我们会学习编写单元测试,通过单元测试的方式来保证我们的代码正确性。

编辑此页 (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
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式