目录
  1. 1. 前言
  2. 2. Axios优势
  3. 3. 安装
  4. 4. 例子
  5. 5. Axios API
    1. 5.1. Axios 请求
    2. 5.2. 请求方法
    3. 5.3. 并发请求
  6. 6. config 配置
  7. 7. 响应结构
  8. 8. Axios 实例
  9. 9. 默认配置
  10. 10. 拦截器
  11. 11. 使用 application/x-www-form-urlencoded
  12. 12. 封装
Axios HTTP库的使用 - 前端随笔

前言

Axios 是一个基于 promise 的 HTTP 库,用于各种接口请求数据,可以用在浏览器和 node.js 中。


Axios优势

  • 支持 Promise
  • 客户端支持防止 CSRF
  • 丰富的接口 API(并发请求等)
  • 请求/响应拦截器
  • 转换请求和响应数据(自动转换JSON数据等)
  • 取消阻止请求

安装

1
$ npm install axios --save

例子

执行 GET 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
axios.get('http://api.example.com/user?ID=12345')
.then(res => {
// 请求成功,处理请求数据
console.log(res);
})
.catch(error => {
// 请求失败,执行错误操作
console.log(error);
});

// GET 请求params参数也可直接添加在配置参数中
axios.get('http://api.example.com/user', {
params: {
ID: 12345
}
})
.then()
.catch()

执行 POST 请求:

1
2
3
4
5
6
7
8
9
10
11
12
axios.post('http://api.example.com/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(res => {
// 请求成功,处理请求数据
console.log(response);
})
.catch(error => {
// 请求失败,执行错误操作
console.log(error);
});

Axios API

Axios 请求

可以通过 axios 传递配置参数来创建请求:

axios(config)

1
2
3
4
5
6
7
8
9
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});

axios(url[, config])

1
2
// 发送 GET 请求,没有配置method,默认 GET
axios('/user/12345');

请求方法

Axios 为所有支持的请求方法提供了别名。

axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

当使用别名方法时,url, method, data 这些属性不必在 config 配置中指定。


并发请求

Axios 处理并发请求的两个助手函数:

  1. axios.all([]) : 用于发送并发请求;
  2. axios.spread(callback) : 用于请求数据回调;
1
2
3
4
5
6
7
8
9
10
11
axios.all([axios('api/account'), axios('api/config')])
.then(axios.spread(function (res1, res2) { // axios.spread() 回调指定多个返回数据
// 两个请求都执行完成后执行
}));

// 不使用 axios.spread() 则会将多个返回数据放入数组中
axios.all([axios('api/account'), axios('api/config')])
.then(res => { // 此时rep为多个请求数据返回的数组
console.log(res[0]); // rep[0] 为第一个请求返回
console.log(res[1]); // rep[1] 为第二个请求返回
}));

config 配置

创建请求时可以指定配置选项,其中只有 url 时必需的。

常见的配置有:

  • url : 指定请求服务器地址;
  • method : 指定请求方法;
  • baseURL : 指定请求基础地址,会自动加在url前面,除非url是一个绝对地址;
  • headers : 指定请求头;
  • params : 指定URL中的params参数;
  • data : 指定发送数据,只适用于POSTPUTPATCH 方法;
  • timeout : 指定请求超时时间,单位毫秒;
  • responseType : 指定响应数据类型,默认json;
  • proxy : 指定代理服务器;

以下为所有可以使用的配置选项:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
{
// 用于请求的服务器 URL
url: '/user',

// method 请求方法
method: 'get', // 默认是 get

// baseURL 将自动加在 url 前面,除非 url 是一个绝对 URL。
baseURL: 'https://some-domain.com/api/',

// transformRequest 允许在向服务器发送前,修改data中的请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
transformRequest: [function (data) {
// 对 data 进行任意转换处理

return data;
}],

// transformResponse 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (res) {
// 对 response 进行任意转换处理

return res;
}],

// headers 自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},

// params 是即将与请求一起发送的 URL 参数,必须是一个无格式对象(plain object)或 URLSearchParams 对象
params: {
ID: 12345
},

// paramsSerializer 是一个负责 params 序列化的函数
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function(params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},

// data 是作为请求主体被发送的数据
// 只适用于这些请求方法 PUT, POST, 和 PATCH
// 在没有设置 transformRequest 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
data: {
firstName: 'Fred'
},

// timeout 指定请求超时的毫秒数(0 表示无超时时间)
timeout: 1000,

// withCredentials 表示跨域请求时是否需要使用凭证
withCredentials: false, // 默认false

// adapter 允许自定义处理请求,以使测试更轻松
// 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
adapter: function (config) {
/* ... */
},

// auth 表示应该使用 HTTP 基础验证,并提供凭据
// 这将设置一个 Authorization 头,覆写掉现有的任意使用 headers 设置的自定义 Authorization头
auth: {
username: 'janedoe',
password: 's00pers3cret'
},

// responseType 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default

// xsrfCookieName 是用作 xsrf token 的值的cookie的名称
xsrfCookieName: 'XSRF-TOKEN', // default

// xsrfHeaderName 是承载 xsrf token 的值的 HTTP 头的名称
xsrfHeaderName: 'X-XSRF-TOKEN', // default

// onUploadProgress 允许为上传处理进度事件
onUploadProgress: function (progressEvent) {
// 对原生进度事件的处理
},

// onDownloadProgress 允许为下载处理进度事件
onDownloadProgress: function (progressEvent) {
// 对原生进度事件的处理
},

// maxContentLength 定义允许的响应内容的最大尺寸
maxContentLength: 2000,

// validateStatus 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 validateStatus 返回 true (或者设置为 null 或 undefined),promise 将被 resolve; 否则,promise 将被 rejecte
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认的
},

// maxRedirects 定义在 node.js 中 follow 的最大重定向数目
// 如果设置为0,将不会 follow 任何重定向
maxRedirects: 5, // 默认的

// httpAgent 和 httpsAgent 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
// keepAlive 默认没有启用
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),

// proxy 定义代理服务器的主机名称和端口
// auth 表示 HTTP 基础验证应当用于连接代理,并提供凭据
// 这将会设置一个 Proxy-Authorization 头,覆写掉已有的通过使用 header 设置的自定义 Proxy-Authorization 头。
proxy: {
host: '127.0.0.1',
port: 9000,
auth: : {
username: 'mikeymike',
password: 'rapunz3l'
}
},

// cancelToken 指定用于取消请求的 cancel token
cancelToken: new CancelToken(function (cancel) {
})
}

响应结构

Axios 请求响应包含以下信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
// data 由服务器提供的响应数据
data: {},

// status 来自服务器响应的 HTTP 状态码
status: 200,

// statusText 来自服务器响应的 HTTP 状态信息
statusText: 'OK',

// headers 服务器响应的头
headers: {},

// config 是为请求提供的配置信息
config: {}
}

请求成功以上响应信息会出现在 response 对象中:

1
2
3
4
5
6
7
8
axios.get('/user/1111')
.then(res => {
console.log(res.data);
console.log(res.status);
console.log(res.statusText);
console.log(res.headers);
console.log(res.config);
});

请求失败时,响应信息会出现在 error.response 对象中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
axios.get('/user/12345')
.catch(function (error) {
if (error.response) {
// 请求以发出,但服务器响应状态码不在 2xx 范围内
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 请求被发出,但没有接收到响应
// error.request 在浏览器中是一个XMLHttpRequest的实例,在 node.js 中是http.ClientRequest
console.log(error.request);
} else {
// 请求未发出,触发了错误
console.log('Error', error.message);
}
console.log(error.config);
});

Axios 实例

一般使用中,项目可能不只包含一个API接口,每个接口可能有不同的默认配置对象,也有可能需要为每个接口设置不同的拦截器,所以并不会直接使用 axios 对象来发送请求,而是创建一个 Axios 实例来对接口做一个封装,再通过实例来发送请求。

axios.create(config)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建实例,实例配置对象为每次调用时的默认属性。
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});

// 此时instance就是axios的一个实例,axios的所有方法及方法别名都可以直接通过实例调用。
instance({
url: '/user',
params: {
id: 12345
}
});

instance.get('/user?id=12345');

默认配置

可以指定请求时的默认配置,避免每次请求来重复配置。

通过 axios.defaults 修改全局默认配置:

1
2
3
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

注:一般也不会去修改全局默认配置,而是通过创建实例建立默认配置或修改。

自定义实例默认配置:

1
2
3
4
5
6
7
8
// 创建实例时就指定默认配置
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000
})

// 也可在创建实例后修改默认配置,同全局修改一致
instance.defaults.timeout = 2500;

默认配置的优先级遵循向上查找:
发送请求时配置 > 实例默认配置 > 全局默认配置


拦截器

拦截器是在发送请求或得到响应处理前拦截,从而对数据进一步操作再发送请求或响应,及在被 thencatch 前拦截。

使用场景:

  • 对请求统一做错误处理;
  • token 处理(是否携带token等);

axios.interceptors.request.use() : 请求拦截器;

axios.interceptors.respones.use() : 响应拦截器;

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
// 请求拦截器:可传入两个回调函数,对应请求前和请求失败时的回调函数。也可只传入请求前回调函数。
axios.interceptors.request.use(config => { // config 配置对象

// 发送请求前,即操作配置对象

return config; // 拦截后必须将配置对象返回
}, error => {

// 请求失败拦截,操作error对象

return Promise.reject(error); // 同样必须返回
});



// 响应拦截器,两个回调函数,对应响应成功和响应失败时的回调函数
axios.interceptors.response.use(res => {

// 操作响应数据,response对象

return res; // 必须返回
}, error => {
// 响应错误拦截
return Promise.reject(error);
});

同样,一般不会在axios中添加全局拦截器,而是在实例中添加拦截器:

1
2
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});

移除拦截器:

1
2
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);

使用 application/x-www-form-urlencoded

默认情况下,axios 将数据对象序列化为JSON 来发送请求,某些接口可能需要使用 application/x-www-form-urlencoded 格式发送数据,首先需要指定请求头的 content-type ,再者需要将数据序列化为对应格式。

可利用第三方库 qs 来序列化数据,而且qs库在很多依赖包中都有使用到,不用重新下载依赖,直接引入使用。

node中可使用 querystring 模块,用法与qs基本相同。

1
2
3
4
5
6
7
8
9
10
import axios from 'axios';
import qs from 'qs';

const data = { id: '888', name: 'Vincent' };
axios({
url: 'https://api.example.com/user'
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data)
});

关于 qs 库,这里列举序列化和解析,其它方法详情可戳这里

1
2
3
4
5
6
7
// 数据序列化,将 js 对象序列化成 url 格式的字符串。
const data = { id: '888', name: 'Vincent' };
qs.stringify(data); // "id=888&name=Vincent"

// 解析,将 url 格式解析成js对象
const str = "firstName=Vincent&lastName=F0ng";
qs.parse(url); // { firstName = "Vincent", lastName = "F0ng"}

封装

创建 axiose 实例及默认配置:

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
// @/api/request.js
import axios from 'axios'

export function request(config) {
// 1.创建axios的实例
const instance = axios.create({
baseURL: 'http://api.example.com',
timeout: 5000
})

// 2.设置post请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// 3.axios的拦截器
// 请求拦截
instance.interceptors.request.use(config => {
// ...
return config
}, err => {
// ...
return Promise.reject(error);
})

// 响应拦截
instance.interceptors.response.use(res => {
// ...
return res.data
}, err => {
// ...
return Promise.reject(err);
})

// 4.发送真正的网络请求
return instance
}

封装接口请求函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// @api/api.js
import { request } from "./request";

export function getMultidata() {
return request({
url: '/home/multidata'
})
}

export function getList(type, page) {
return request({
url: '/home/data',
params: {
type,
page
}
})
}

接口调用:

1
2
3
4
5
6
7
8
9
10
11
import { getMultidata, getList} from "@/api/api.js"

getMultidata().then(res => {
// ...
}).catch(err => {
// ...
});

getList().then(res => {

});

封装的意义:在使用第三方库时,可能面临更换库的时候,如果每个请求都调用 aixos ,更换库时所有使用到 aixos 的地方都需要修改。而如上封装,返回的是 promise 对象,即使更换库也只需要修改 @/api/request.js 文件,确保返回的同样是一个 promise 对象即可。


文章作者: Vincent F0ng
文章链接: https://vincef0ng.cn/post/axios/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Vincent F0ng

评论(支持Markdown)