axios介绍
axios是基于promise的网络请求库,可以在nodejs和浏览器中运行。在服务端axios使用原生的nodejs的http模块,在客户端浏览器中则而是用xmlhttprequests,本质是对XHR的封装,只不过是promise的实现版本;
功能:
- 从浏览器中创建 XMLHttpRequest
- 从 node.js 中创建 http 请求
- 支持 Promise API
- 拦截请求和响应和转换数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防止 XSRF 攻击
开始封装:
1,新建myAxios.js和backend.js;
myAxios主要是对axios的封装,而backend是对后端状态码的判断;
myAxios.js:
import Axios from 'axios';
import {
ErrorToken, GlobalResponseCode, BusinessResponseCode, ApiResult } from '@/api/backend';
import router from '@/router';
// 全局配置
const axios = Axios.create({
timeout: 60 * 1000, // 超时时间 1分钟
headers: {
'Content-Type': 'application/json;charset=UTF-8' }, // axios默认的请求类型 json类型进行传输
});
/* 请求拦截处理token的情况 请求头里面可以随意添加属性 */
axios.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.authToken = token;
}
return config;
});
// 响应拦截
axios.interceptors.response.use(
(response) => {
// 我们一般在这里处理,请求成功后的错误状态码 例如状态码是500,404,403
return Promise.resolve(response);
},
(error) => {
// 服务器响应发生错误时的处理
Promise.reject(error);
}
);
/* 定义类 */
/* 注意 get多次相同的请求会出现304 post就不会 */
class MyAxios {
// 1,get请求
get(url, params) {
console.log('params', params);
return this.request(axios.get(url, params));
}
// 2,post请求
post(url, data) {
return this.request(axios.post(url, data));
}
// 3,put请求
put(url) {
return this.request(axios.put(url));
}
/**统一响应封装 */
async request(axiosRequest) {
try {
const res = await axiosRequest;// axios请求会返回一个promise所以此处使用await进行接收 如果有异常使用 try catch进行捕获
// 请求失败的情况
if (!res.data || res.data.code != '000000') {
this.resCodePrompt(res.data.code);
console.warn('SeverError', res);
// 处理失败结果
return new ApiResult().setError(res.data);
}
// 请求成功的处理
return new ApiResult().setSuccess(res.data);
} catch (error) {
// TODO 这里需要验证失败的情况
const res = error.response;
// 根据状态吗进行提示
this.resErrorPrompt(res);
return new ApiResult().setNetworkError();
}
}
/**效验返回码 */
resCodePrompt(resCode) {
// 判断是否是token的问题
if (ErrorToken.includes(resCode)) {
this.$message({
type: 'error', message: '登录凭证无效,请重新登录' });
router.push('/login');
}
// 判断不是token的问题
const message = GlobalResponseCode[resCode] || BusinessResponseCode[resCode];
if (message) {
return this.$message({
type: 'error', message: '登录凭证无效,请重新登录' });
}
}
/**错误的返回码处理 */
resErrorPrompt(res) {
if (!res) {
this.$message({
type: 'error', message: '网络错误!' });
} else if (res.status === 404) {
this.$message({
type: 'error', message: '找不到资源!' });
} else if (res.status === 500) {
this.$message({
type: 'error', message: '内部错误!' });
} else {
// 其余统一提示状态码
this.$message({
type: 'error', message: `${
res.status}` });
}
}
}
export const myAxios = new MyAxios();
backend.js
/**结果封装 */
export class ApiResult {
/**请求是否成功 */
isSuccess = false;
/**请求结果状态 */
stu = RequestStu.success;
/**状态码 */
code = '000000';
/**描述信息 */
msg = '';
/**请求结果数据 */
data = null;
/**后端返回成功 */
setSuccess(res) {
this.isSuccess = true;
this.stu = RequestStu.success;
this.msg = res.msg;
this.data = res.data;
this.code = res.code;
console.log('this:', this);
return this;
}
/** 后端返回失败 */
setError(res) {
this.stu = RequestStu.error;
this.msg = res.msg;
this.code = res.code;
return this;
}
/** 网络错误 */
setNetworkError() {
this.stu = RequestStu.networkError;
return this;
}
}
/**错误响应吗 关于token验证的 */
export const ErrorToken = ['000002', '000003', '000004'];
/**全局响应码 000000--000100(包括000000和000100)*/
export const GlobalResponseCode = {
/**成功*/
'000000': '成功',
/**请求失败 */
'000001': '请求失败',
/**令牌为空 */
'000002': '请重新登录',
/**令牌过期 */
'000003': '请重新登录',
/**令牌无效 */
'000004': '请重新登录',
/**非法请求 */
'000005': '非法请求',
/**参数非法 */
'000006': '参数非法',
/**参数为空 */
'000007': '数据为空',
};
/**关于业务逻辑上的响应码 */
export const BusinessResponseCode = {
/**账号不存在 */
'000101': '账号信息有误,请确认',
/**图片验证码不一致 */
'000102': '图片验证码有误',
/**短信验证码不一致 */
'000103': '短信验证码错误',
/**与保单绑定的手机号不一致 */
'000104': '手机号有误,请确认',
/**未勾选同意条款 */
'000105': '请先勾选保单设计须知。',
/**短信验证码获取频繁 */
'000106': '短信验证码获取频繁',
/**修改保单失败 */
'000107': '修改失败',
/**添加保单信息失败 */
'000108': '添加保单信息失败',
/**保单已存在 */
'000109': '保单已存在',
/**内部错误 */
'000110': '内部错误',
/**保单设计已完成 */
'000111': '保单设计已完成',
/**获取图片信息失败 */
'000112': '获取图片失败,请刷新重试',
'000113': '图片保存失败,请重试',
'000114': '上传文件过大,请重新上传',
'000115': '文件上传失败,请重新上传',
'000116': '已参加该活动',
'000117': '活动已结束',
'000118': '参加的活动不存在',
};
/**请求状态 */
export const RequestStu = {
/** 请求成功 */
success: 'success',
/** 请求错误 */
error: 'error',
/** 连接失败 */
networkError: 'networkError',
};
2,使用
1,比如有一个登陆接口 ;我们需要封装一下:
import {
myAxios } from '../myAxios';
const prefix = '/backend'
export default {
/* 请求登录接口 get请求 普通的get请求和post请求 */
queryLogin(mobileNo) {
return myAxios.get(`${
prefix}/api/user/login`, mobileNo);
},
};
2,然后再vue组件中请求这个接口:
methods: {
async handleLogin() {
// 非空判断
if (!this.loginForm.account || !this.loginForm.password) {
return this.$message('账号或者密码不能为空!');
}
// 调用此接口 解构数据
const {
isSuccess, data, code } = await api.login.queryLogin({
account: 'xinjie1',
password: '123456789',
});
// 请求失败的处理
if (!isSuccess) {
return this.$message({
type: 'error', message: code });
}
// 请求成功的处理 data
console.log(data)
....
}
}
3,vue配置接口代理,解决开发环境中的跨域问题;vue.config.js配置如下:
// 服务端ip 需要代理的地址
const api = 'http://10.11.12.181:26341';
/* 开发环境跨域情况的代理配置 */
devServer: {
/* 接口代理器设置 可以配置多个*/
proxy: {
'/backend': {
// 实际访问的服务器地址
target: api,
// 控制服务器收到的请求头中Host字段的值 host就是主机名加端口号 实际上就是欺骗后端服务器
changeOrigin: true,
// 是否启用websockets
ws: false,
// 重写请求路径 开头是/api的替换为 空串
pathRewrite: {
'/api': '' },
},
},
},
4,如果是上传文件,需要使用formData,接口封装需要处理一下:
import {
myAxios } from '../myAxios';
const prefix = '/backend'
export default {
/* formData 文件上传 */
uploadImg(policyId, policyNo, file) {
const formData = new FormData();
formData.append('policyId', policyId.toString());
formData.append('policyNo', policyNo);
formData.append('uploadFile', file);
// 添加文件上传的请求头
const axiosConfig = {
headers: {
'Content-Type': 'multipart/form-data',
},
timeout: 10000, //超时时间
// 表示允许在向服务器发送前,修改请求数据
transformRequest: [
function (data, headers) {
return data;
},
],
};
return myAxios.post(`${
prefix}/api/user/uploadImg`, formData, {
axiosConfig: axiosConfig });
},
}