# 1. 前言
在上篇文章中,我们实现了混合对象axios
,我们既可以把axios
当做函数来调用,又能从它身上点出一些快捷接口使用。但是当我们把axios
当做函数来调用时,该函数只能接受一个参数,那就是请求配置对象config
,而官方的axios
不仅能跟我们一样接收一个参数,它还支持接收两个参数:请求的url
和除url
外的其他配置对象config
,像这样:
// 接收一个参数
axios({
url: "/api/addParameters",
method: "post",
data: {
msg: "hi",
},
});
// 接收两个参数
axios("/api/addParameters", {
method: "post",
data: {
msg: "hello",
},
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
虽然这个功能好像看起来有点鸡肋,但是我们为了跟官方保持一致,接下来就来实现它。
# 2. 需求分析
一个函数在调用时既可以传一个参数也可以传两个参数,这就是函数的重载。
函数重载:在相同的声明域中的函数名相同的,而参数表不同的,即通过函数的参数表而唯一标识并且来区分函数的一种特殊的函数。
在一些强类型语言中,如C++
、java
等中,函数重载是个很重要的概念,而javaScript
是门弱类型语言,它本身是没有函数重载这个概念的,但是我们可以通过一些技巧来模拟出函数重载的效果。
说了这么多,其实就想说,这个功能可以利用函数重载来实现。虽然JS
没有重载,但是我们可以通过判断传入的参数不同来处理不同的逻辑,最终实现重载效果。
OK,接下来就让我们来实现这个功能吧。
# 3. 改写 axios.request 方法
我们知道,把混合对象axios
当做函数调用时其实是调用了Axios
类中的request
方法,所以我们就在request
方法里面实现函数的重载。
// src/core/Axios.ts
export default class Axios {
request(url: any, config?: any): AxiosPromise {
if (typeof url === "string") {
config = config ? config : {};
config.url = url;
} else {
config = url;
}
return dispatchRequest(config);
}
// ...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
代码说明:
- 我们给
request
方法增加一个参数url
,并把url
和config
参数类型都设置为any
; - 然后判断传入的
url
是否为string
类型,如果是,表明用户第一个参数传入了url
,接着在判断是否传入了config
,如果没有传入则赋给默认值空对象{}
,然后再将传入的url
赋给config
中的url
上; - 如果传入的
url
不是string
类型,我们就认为用户只传入了一个参数,并且该参数就是请求的配置对象config
; - 最后,依然是调用
dispatchRequest(config)
将请求发出;
总结一下就是:
如果传入的第一个参数是string
类型,我们就认为用户是以传入两个参数的形式调用混合对象axios
函数的,那么就把传入的url
添加到config
上再发出请求。
如果传入的第一个参数不是string
类型,我们就认为用户是以传入一个参数的形式调用混合对象axios
函数的,那么就把这个参数当做config
发出请求。
最后,别忘了还要给混合对象axios
接口类型上添加重载的函数类型:
export interface AxiosInstance extends Axios {
(config: AxiosRequestConfig): AxiosPromise;
(url: string, config?: AxiosRequestConfig): AxiosPromise;
}
2
3
4
OK,函数重载就已经实现完毕了,接下来,我们就来编写demo
看看效果如何。
# 4. demo 编写
在 examples
目录下创建 addParameters
目录,在 addParameters
目录下创建 index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>addParameters demo</title>
</head>
<body>
<script src="/__build__/addParameters.js"></script>
</body>
</html>
2
3
4
5
6
7
8
9
10
接着再创建 app.ts
作为入口文件:
import axios from "../../src/axios";
axios({
url: "/api/addParameters",
method: "post",
data: {
msg: "hi",
},
});
axios("/api/addParameters", {
method: "post",
data: {
msg: "hello",
},
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
接着在 server/server.js
添加新的接口路由:
// axios增加参数
router.post("/api/addParameters", function(req, res) {
res.json(req.body);
});
2
3
4
最后在根目录下的index.html
中加上启动该demo
的入口:
<li><a href="examples/addParameters">addParameters</a></li>
OK,我们在命令行中执行:
# 同时开启客户端和服务端
npm run server | npm start
2
接着我们打开 chrome
浏览器,访问 http://localhost:8000/ (opens new window) 即可访问我们的 demo
了,我们点击 addParameters
,通过F12
的 network
部分我们可以看到所有的请求都已正常发出:
← 11.接口扩展 13.让响应数据支持泛型 →