# 1. 前言
在响应回来处理响应结果时,我们需要先判断一下XMLHttpRequest
响应中的数字状态码是否是一个合法值,如果是一个我们认定的合法值,那么我们就继续进行下一步操作,如果不是,则做其他操作,如抛出异常等。在之前的代码中,我们把判断响应状态码是否合法是直接写死在代码里的,我们简单的认为当状态码在 200 到 300 之间时候它是合法的,否则即为不合法。虽然这样符合大多数用户的业务场景,但是我们这样武断的直接写死在代码里显然是不行的,因为我们毕竟覆盖不了所有用户的业务场景。这就要求状态码合法性的校验规则应该是由用户可配置的。
而在官方axios
中,在请求配置对象里提供了validateStatus
属性,该属性值是一个状态码校验函数,接收状态码作为函数参数,返回校验结果true
或false
,并且这个属性也在默认请求配置对象中。官方文档是这么介绍的:
// `validateStatus` defines whether to resolve or reject the promise for a given
// HTTP response status code. If `validateStatus` returns `true` (or is set to `null` or `undefined`),
// the promise will be resolved; otherwise, the promise will be rejected.
validateStatus: function (status) {
return status >= 200 && status < 300; // default
}
2
3
4
5
6
如果validateStatus
函数返回true
,或者validateStatus
属性值被设置为null
,或者没有用户配置了validateStatus
属性但是没有定义校验函数的时候,都认为是合法的,正常 resolve(response)
,否则都会抛出异常。
搞明白官方axios
中的validateStatus
属性功能后,那么接下里,我们也要为我们的axios
添加validateStatus
属性,并实现其功能。
# 2. 向请求配置对象添加属性
向请求配置对象config
中添加 validateStatus
属性之前,我们需要先在src/types/index.ts
中的配置对象的接口类型定义AxiosRequestConfig
上添加该属性的定义,如下:
export interface AxiosRequestConfig {
// 新增
validateStatus?: (status: Number) => Boolean;
}
2
3
4
添加好属性接口后,我们还要给默认请求配置对象src/default.ts
中添加这两个属性,并且属性的默认值跟官方axios
保持一直,如下:
const defaults: AxiosRequestConfig = {
// 新增
validateStatus(status: Number): boolean {
return status >= 200 && status < 300;
},
};
2
3
4
5
6
# 3. 修改之前的状态码判断逻辑
在之前的代码中,我们把判断响应状态码是否合法是直接写死在代码里的,现在我们应该调用用户传入的状态码校验函数,用它来校验状态是否合法,如下:
function handleResponse(response: AxiosResponse): void {
if (!validateStatus || validateStatus(response.status)) {
resolve(response);
} else {
reject(
createError(
`Request failed with status code ${response.status}`,
config,
null,
request.status,
response
)
);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如果validateStatus
函数返回true
,或者validateStatus
属性值被设置为null
,或者没有用户配置了validateStatus
属性但是没有定义校验函数的时候,都认为是合法的,正常 resolve(response)
,否则都会抛出异常。
OK,validateStatus
属性就添加好了,并且状态码判断逻辑也修改了。接下来,我们就来编写demo
来测试下效果如何。
# 4. demo 编写
在 examples
目录下创建 checkStatus
目录,在 checkStatus
目录下创建 index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>checkStatus demo</title>
</head>
<body>
<script src="/__build__/checkStatus.js"></script>
</body>
</html>
2
3
4
5
6
7
8
9
10
接着再创建 app.ts
作为入口文件:
import axios from "../../src/axios";
axios.get("/api/checkStatus").then((res) => {
console.log(res);
});
axios
.get("/api/checkStatus", {
validateStatus: (status) => status >= 200 && status < 400,
})
.then((res) => {
console.log(res);
});
2
3
4
5
6
7
8
9
10
11
12
13
接着在 server/server.js
添加新的接口路由:
// 请求状态码合法性校验
router.get("/api/checkStatus", function(req, res) {
res.status(304);
res.end();
});
2
3
4
5
在本demo
我们发送了两个请求,一个请求没有配置validateStatus
属性,它会使用默认请求对象中的validateStatus
校验函数,即判断状态码是否在 200 到 300 之间;第二个请求我们配置了validateStatus
属性,并且配置了校验函数,判断状态是否在 200 到 400 之间。另外,在服务端路由接口中,我们故意把响应状态设置为 304,这样第一个请求就会校验不通过抛出异常,第二个请求将会校验通过。
最后在根目录下的index.html
中加上启动该demo
的入口:
<li><a href="examples/checkStatus">checkStatus</a></li>
OK,我们在命令行中执行:
# 同时开启客户端和服务端
npm run server | npm start
2
接着我们打开 chrome
浏览器,访问 http://localhost:8000/ (opens new window) 即可访问我们的 demo
了,我们点击 checkStatus
,就可以看到请求都已经正常发出,在控制台上第一个请求抛出了状态码异常,第二个请求正常响应了。
OK,以上就是为我们的axios
添加validateStatus
属性,并实现了其功能。