前言
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); });
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
| axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } });
|
axios(url[, config])
请求方法
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 处理并发请求的两个助手函数:
axios.all([])
: 用于发送并发请求;
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.all([axios('api/account'), axios('api/config')]) .then(res => { console.log(res[0]); console.log(res[1]); }));
|
config 配置
创建请求时可以指定配置选项,其中只有 url
时必需的。
常见的配置有:
url
: 指定请求服务器地址;
method
: 指定请求方法;
baseURL
: 指定请求基础地址,会自动加在url前面,除非url是一个绝对地址;
headers
: 指定请求头;
params
: 指定URL中的params参数;
data
: 指定发送数据,只适用于POST
、PUT
、PATCH
方法;
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: '/user',
method: 'get',
baseURL: 'https://some-domain.com/api/',
transformRequest: [function (data) {
return data; }],
transformResponse: [function (res) {
return res; }],
headers: {'X-Requested-With': 'XMLHttpRequest'},
params: { ID: 12345 },
paramsSerializer: function(params) { return Qs.stringify(params, {arrayFormat: 'brackets'}) },
data: { firstName: 'Fred' },
timeout: 1000,
withCredentials: false,
adapter: function (config) { },
auth: { username: 'janedoe', password: 's00pers3cret' },
responseType: 'json',
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
onUploadProgress: function (progressEvent) { },
onDownloadProgress: function (progressEvent) { },
maxContentLength: 2000,
validateStatus: function (status) { return status >= 200 && status < 300; },
maxRedirects: 5,
httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }),
proxy: { host: '127.0.0.1', port: 9000, auth: : { username: 'mikeymike', password: 'rapunz3l' } },
cancelToken: new CancelToken(function (cancel) { }) }
|
响应结构
Axios 请求响应包含以下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| { data: {},
status: 200,
statusText: 'OK',
headers: {},
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) { console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { 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({ 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;
|
默认配置的优先级遵循向上查找:
发送请求时配置 > 实例默认配置 > 全局默认配置
拦截器
拦截器是在发送请求或得到响应处理前拦截,从而对数据进一步操作再发送请求或响应,及在被 then
或 catch
前拦截。
使用场景:
- 对请求统一做错误处理;
- 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 => { return config; }, error => { return Promise.reject(error); });
axios.interceptors.response.use(res => { 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);
|
默认情况下,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
| const data = { id: '888', name: 'Vincent' }; qs.stringify(data);
const str = "firstName=Vincent&lastName=F0ng"; qs.parse(url);
|
封装
创建 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
| import axios from 'axios'
export function request(config) { const instance = axios.create({ baseURL: 'http://api.example.com', timeout: 5000 }) instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
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); })
return instance }
|
封装接口请求函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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
对象即可。