你知道吗?axios 请求是 JSON 响应优先的

本文是“axios源码系列”第二篇。上文我们介绍了 axios 中是如何实现取消请求 的,本文我将介绍另一个话题:axios 是 JSON 响应优先的。

那为什么这么说呢?我们能从 2 个方面的表现进行阐述。

表现一:默认请求头

你可能没有注意到,每个 axios 请求默认会有 2 个请求头配置,位于 lib/defaults/index.js

1
2
3
4
5
6
7
8
9
10
js复制代码// /v1.6.8/lib/defaults/index.js#L144
const defaults = {
// ...
headers: {
common: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': undefined
}
}
}
  1. 首先,明确告知服务器,我能接受 JSON 数据响应。
  2. 其次,不发送 Content-Type 头信息。

这块配置会在请求发出前,与用户传入的 config.headers 进行合并。

1
2
js复制代码// /v1.6.8/lib/core/Axios.js#L72
config = mergeConfig(this.defaults, config);

接着扁平化,将 config.headers 处理成 AxiosHeaders 实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
js复制代码// /v1.6.8/lib/core/Axios.js#L100-L113
// Flatten headers
let contextHeaders = headers && utils.merge(
headers.common,
headers[config.method]
);

headers && utils.forEach(
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
(method) => {
delete headers[method];
}
);

config.headers = AxiosHeaders.concat(contextHeaders, headers);

AxiosHeaders 类似于标准 Headers API,提供了各种操作头信息的方法,比如 get()、set()、concat() 等。

看下最终请求头效果。

这就是 axios 是 JSON 响应优先的第一个表现。

表现二:响应数据处理

不过重要的还是第二个表现,即在处理响应数据的时候。

我们都知道,我们可以为 axios 请求指定 responseType 配置项。以下面代码为例:

1
2
3
4
5
6
7
js复制代码axios.get('https://httpstat.us/200', {
responseType: 'json'
})
.then(res => {
console.log(res)
// { data: {code: 200, description: 'OK'} }
})

这里我们告知 axios,响应数据是 JSON 格式的,需要处理成 JSON 对象给我们。

但这个配置项是可选的,因为 axios 默认就会把响应数据看做 JSON 格式处理

这块逻辑跟另一个配置项 transformResponse 有关。

如果你没有自定义 transformResponse 这个配置项,那么它的默认逻辑如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
js复制代码// /blob/v1.6.8/lib/defaults/index.js#L99
const defaults = {
// ...
transformResponse: [function transformResponse(data) {
const JSONRequested = this.responseType === 'json';

if (
typeof data === 'string' &&
(!this.responseType || JSONRequested)
) {
try {
return JSON.parse(data);
} catch (e) {}
}

return data;
}],
// ...
}

transformResponse 配置项接收请求返回的响应数据 data,决定最终返回的数据类型。而 data 的来源如下(以浏览器端实现为例)。

1
2
3
4
js复制代码// /v1.6.8/lib/adapters/xhr.js#L100
const responseData = !responseType || responseType === 'text' || responseType === 'json'
? request.responseText
: request.response;

这里的 responseType,是从传入用户的 config 里获取的。

1
2
js复制代码// /v1.6.8/lib/adapters/xhr.js#L52
let {responseType, withXSRFToken} = config;

观察就能知道:当传入的 config 没有包含 responseType,或 responseType 值为 ‘text’ 或 ‘json’ 时,data 即 request.responseText,也就是一个字符串。

回到刚才的逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
js复制代码transformResponse: [function transformResponse(data) {
const JSONRequested = this.responseType === 'json';

if (
typeof data === 'string' &&
(!this.responseType || JSONRequested)
) {
try {
return JSON.parse(data);
} catch (e) {}
}

return data;
}],

如果 responseType 没有设置,或者 responseType 被设置成 ‘json’。那么就以 JSON.parse(data) 方式处理并返回。

看,这里的 data 属性就是一个 JS 对象了。

如果把 responseType 被设置成 ‘text’,返回的就是没经过任何处理的字符串了。

1
2
3
js复制代码axios.get('https://httpstat.us/200', {
responseType: 'text'
})

效果如下。

这就是 axios 是 JSON 响应优先的第二个表现,也是直接原因。

总结

本文带大家了解了 axios 的另一个特性,它是 JSON 响应优先的。也就是说,JSON 响应在 axios 中是“一等公民”。

这并不难理解,因为目前几乎所有前端项目都在使用 JSON 格式返回响应数据。因此,这种默认设置也减少了一些样板代码的编写,提升了开发体验。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%