axios的封装

axios的封装

axios是一个基于promise的http库,主要用来对api的请求接口,返回结果进行封装

常用设置

  • axios.defaults.timeout = 10000; 默认请求超时时间,如果超过,会通知用户重新刷新页面
  • axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; 请求头的设置

请求拦截

  • 有的时候,页面需要用户登录才能访问,或者是需要序列化我们的post数据
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
service.interceptors.request.use(
config => {
//定义取消请求函数
let cancel = undefined;
config.cancelToken = new axios.CancelToken(function executor(c) {
cancel = c;
});
//放置重复请求
let nowTime = new Date().getTime();
requestList = requestList.filter((item) => {
return (item.setTime + saveTime) > nowTime;
});
let sessionUrl = requestList.filter((item) => {
return item.url === config.url;
});
if (sessionUrl.length > 0) {
console.info(config.url + '请求重复 中断请求!');
cancel(config.url)
return;
}
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
let login_token = Cookies.get("login_token");
if (login_token) {
config.headers.Authorization = login_token;
return config;
}
return config;
},
error => {
// Do something with request error
return Promise.reject(error);
}
);

响应的拦截

  • 比如,后台返回给前台的错误码是404,5xx之类的错误时,我们并不想让用户知道这些错误信息,因此让用户看到另外一个页面,优化体验
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
service.interceptors.response.use(
response => {
store.commit('setNetworkState',true);
let result=response.data;
if(result.state){
return Promise.resolve(result.data);
}else{
Message({type:'error',message:result.msg});
if(result.code === 401){
setTimeout(() => {
Cookies.set("return_url",process.env.FRONT_ROOT + '/#' + router.currentRoute.fullPath,{ domain: process.env.COOKIE_DOMAIN });
window.location.href = process.env.LOGIN_ROOT;
}, 1000);
}else if(result.code === 403){
setTimeout(() => {
router.push('/403');
}, 1000);
}
return Promise.reject(result.msg);
}
},
error => {
console.info(error)
if(error.response){
store.commit('setNetworkState',true);
let status=error.response.status;
let result=error.response.data;
console.info(error.response);
switch(status){
case 400:
Message({type:'error',message:result.msg});
break;
case 401:
Message({type:'error',message:result.msg});
setTimeout(() => {
Cookies.set("return_url",process.env.FRONT_ROOT + '/#' + router.currentRoute.fullPath,{ domain: process.env.COOKIE_DOMAIN });
window.location.href = process.env.LOGIN_ROOT;
}, 1000);
break;
case 403:
setTimeout(() => {
router.push('/403');
}, 1000);
break;
case 404:
setTimeout(() => {
router.push('/404');
}, 1000);
break;
case 405:
Message({type:'error',message:"服务器内部错误,请与管理员联系或稍后重试"});
break;
case 500:
Message({type:'error',message:"服务器内部错误,请与管理员联系或稍后重试"});
break;
default:
Message({type:'error',message:"服务器未知错误,请与管理员联系或稍后重试"});
}
return Promise.reject(error.response);
}
else{
/// 断网了
store.commit('setNetworkState',false);
}
});

封装具体的方法

  • get方法:我们通过定义一个get函数,get函数有两个参数,第一个参数表示我们要请求的url地址,第二个参数是我们要携带的请求参数。get函数返回一个promise对象,当axios其请求成功时resolve服务器返回 值,请求失败时reject错误值。最后通过export抛出get函数
  • post方法:原理同get基本一样,但是要注意的是,post方法必须要使用对提交从参数对象进行序列化的操作,这个很重要,如果没有序列化操作,后台是拿不到你提交的数据的

注意

  • axios.get()方法和axios.post()在提交数据时参数的书写方式还是有区别的。区别就是,get的第二个参数是一个{},然后这个对象的params属性值是一个参数对象的。而post的第二个参数就是一个参数对象。

api的管理

为了方便管理各个页面上的接口,降低代码的耦合度,也可以增加接口的复用,可以将所有的请求接口放到模块中管理进去

  • 可以新建一个文件夹,每个模块一个req.js文件,放入具体涉及到的接口内容
  • index.js api的出口,主要用来export给页面使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      
    // 资源接口
    import article from '@/api/v1/resource';
    // 其他模块的接口……

    // 导出接口
    export default {
    resource,
    // ……
    }
  • base.js 管理接口域名

    1
    2
    3
    4
    5
    6
    7
    // 可以定义多个域名
    const base = {
    sq: 'https://xxxx111111.com/api/v1',
    bd: 'http://xxxxx22222.com/api'
    }

    export default base;
  • 使用的时候,直接引入具体的方法就可以了,和组件的引用类似

    1
    2
    3
    4
    5
    6
    import base from './base'; // 导入接口域名列表
    import axios from '@/utils/http'; // 导入http中创建的axios实例

    /**具体方法接口实现**/

    export default article; //导出具体方法名
- 最后,为了方便,将整个挂载到vue实例(this)上去,通过new Vue对象来实现
- 也可以挂载到vue原型上,但是vuex就无法访问了