axios
基于promise用于浏览器和node.js的http客户端
特点
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 能转换请求和响应数据
- 能取消请求
- 自动转换JSON数据
- 浏览器端支持防止CSRF(跨站请求伪造)
默认配置
全局修改axios默认配置
global.js文件信息
/**
* 全局常量配置
*/
let BASE_URL = "http://localhost:8080";
if (process.env.NODE_ENV === "production") {
BASE_URL = "生成环境url";
}
export default {
BASE_URL,
};
import { BASE_URL } from "@/tool/global";
axios.defaults.baseURL = BASE_URL; // url的配置路径
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
实例默认配置
// 创建实例时修改配置
var instance = axios.create({
baseURL: 'https://api.example.com'
});
// 实例创建之后修改配置
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
配置优先级
配置项通过一定的规则合并,request config
> instance.defaults
> 系统默认
,优先级高的覆盖优先级低的。
请求拦截器
axios请求取消后,如何在此唤醒请求 参考:https://segmentfault.com/q/1010000016399720
axios.interceptors.request.use(config => {
const request = JSON.stringify(config.url) + JSON.stringify(config.data);
// `cancelToken` 指定用于取消请求的 cancel token
config.cancelToken = new CancelToken((cancel) => {
sources[request] = cancel;
});
// 1.判断请求是否已存在请求列表,避免重复请求,将当前请求添加进请求列表数组;
requestList.includes(request) ? sources[request]("取消重复请求") :
requestList.push(request);
// 如果headers中需要携带参数,可在此处配置
// loading
return config;
}, error => {
return Promise.reject(error);
});
响应拦截器
axios.interceptors.response.use(response => {
// 将当前请求从请求列表中删除
const request = JSON.stringify(response.config.url) + JSON.stringify(response.config.data);
requestList.splice(requestList.findIndex(item => item === request), 1);
return response;
}, error => {
return Promise.resolve(error.response);
});
校验状态码
const checkStatus = function(response) {
// loading
// 如果http状态码正常,则直接返回数据
if (response && (response.status === 200 || response.status === 304)) {
return response;
// 如果不需要除了data之外的数据,可以直接 return response.data
}
// 如果 http 状态码是 401 ,则跳转到登录页
if (response && response.status === 401) {
// router.push({path: "/login"});
// isTokenOverdue = false;
sessionTimeout();
}
// 异常状态下,把错误信息返回去,status: -404并无特殊意义,也可定义为其他状态码
return {
status: -404,
msg: "网络异常",
};
};
校验code
const checkCode = function(res) {
// 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误)
if (res.status === -404) {
Vue.prototype.$alert("通讯失败");
// alert(res.msg)
}
// 校验前后端约定的状态码
if (res.data && /^E4[0-9]*/.test(res.data.code)) {
return Promise.reject(res.data);
}
return res.data;
};
封装axios请求
// url: 请求的url,data:请求的参数,config:请求的头部信息, method: 请求的方式
const request = (url, data, config, method) => {
let params = {};
params.params = data;
// get,delete和post,put的参数形式不一样,在此做一层封装
if (method === "post" || method === "put") {
params = data;
}
return axios[method](url, params, config).then(
(response) => {
return checkStatus(response);
}
).then(
(res) => {
return checkCode(res);
}
);
};
封装axios方法
const post = (url, data) => {
return request(url, data, headers, "post");
};
const get = (url, params) => {
return request(url, params, headers, "get");
};
// delete 不可以使用,故命名为deletes,不合适也可以更改
const deletes = (url, params) => {
return request(url, params, headers, "delete");
};
const put = (url, data) => {
return request(url, data, headers, "put");
};
export default {post, get, deletes, put, sources};
使用
这里使用了async-await的方式,不理解的可以看一下这篇文章https://segmentfault.com/a/1190000011526612
import api from "@/common/api";
async loadListData() {
this.loading = true;
const params = this.pageData;
params.page = params.page;
params.processStatus = this.processStatus;
try {
const res = await api.get("你的url", params);
this.listData.length = 0;
this.listData = res.data.content;
this.totalElements = res.data.totalElements;
this.loading = false;
} catch (e) {
console.log(e);
}
},
完整的代码
import Vue from "vue";
import axios from "axios";
import { BASE_URL } from "@/tool/global";
import router from "../router";
// 请求列表
const requestList = [];
// 取消列表
const CancelToken = axios.CancelToken;
const sources = {};
// 基础的url路径
axios.defaults.baseURL = BASE_URL;
// 默认headers
const headers = {"Content-Type": "application/json; charset=UTF-8"};
function sessionTimeout() {
Vue.prototype.$notify.error({
title: "Error",
message: "会话过期了需要重新登陆",
showClose: true,
onClose: function() {
router.push("/login");
// isTokenOverdue = true;
},
});
}
axios.interceptors.request.use(config => {
const request = JSON.stringify(config.url) + JSON.stringify(config.data);
// `cancelToken` 指定用于取消请求的 cancel token
config.cancelToken = new CancelToken((cancel) => {
sources[request] = cancel;
});
// 1.判断请求是否已存在请求列表,避免重复请求,将当前请求添加进请求列表数组;
requestList.includes(request) ? sources[request]("取消重复请求") : requestList.push(request);
// 如果headers中需要携带参数,可在此处配置
// loading
return config;
}, error => {
return Promise.reject(error);
});
axios.interceptors.response.use(response => {
// 将当前请求从请求列表中删除
const request = JSON.stringify(response.config.url) + JSON.stringify(response.config.data);
requestList.splice(requestList.findIndex(item => item === request), 1);
return response;
}, error => {
return Promise.resolve(error.response);
});
const checkStatus = function(response) {
// loading
// 如果http状态码正常,则直接返回数据
if (response && (response.status === 200 || response.status === 304)) {
return response;
// 如果不需要除了data之外的数据,可以直接 return response.data
}
// 如果 http 状态码是 401 ,则跳转到登录页
if (response && response.status === 401) {
// router.push({path: "/login"});
// isTokenOverdue = false;
sessionTimeout();
}
// 异常状态下,把错误信息返回去,status: -404并无特殊意义,也可定义为其他状态码
return {
status: -404,
msg: "网络异常",
};
};
const checkCode = function(res) {
// 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误)
if (res.status === -404) {
Vue.prototype.$alert("通讯失败");
// alert(res.msg)
}
// 校验前后端约定的状态码
if (res.data && /^E4[0-9]*/.test(res.data.code)) {
return Promise.reject(res.data);
}
return res.data;
};
// url: 请求的url,data:请求的参数,config:请求的头部信息, method: 请求的方式
const request = (url, data, config, method) => {
let params = {};
params.params = data;
// get,delete和post,put的参数形式不一样,在此做一层封装
if (method === "post" || method === "put") {
params = data;
}
return axios[method](url, params, config).then(
(response) => {
return checkStatus(response);
}
).then(
(res) => {
return checkCode(res);
}
);
};
const post = (url, data) => {
return request(url, data, headers, "post");
};
const get = (url, params) => {
return request(url, params, headers, "get");
};
// delete 不可以使用,故命名为deletes,不合适也可以更改
const deletes = (url, params) => {
return request(url, params, headers, "delete");
};
const put = (url, data) => {
return request(url, data, headers, "put");
};
export default {post, get, deletes, put, sources};
// example
// 第一种方式
// 需要注意的是,接口返回的数据不再是response.data,而是response,所以对于返回数据的处理上需要注意一下。
// 需要使用async 和 await或者promise
// import api from "@/common/api";
// async loadListData() {
// this.loading = true;
// const params = this.pageData;
// params.page = params.page;
// params.processStatus = this.processStatus;
// try {
// const res = await api.get(“url”, params);
// if (res.code === "S200") {
// this.listData.length = 0;
// this.listData = res.data.content;
// this.totalElements = res.data.totalElements;
// this.loading = false;
// }
// } catch (err) {
// console.log(err);
// }
// },
// 第二种方式
// import api from "@/common/api";
// api.put(“url”, params).then(res => {
// this.$message({
// message: "更新成功",
// type: "success",
// });
// }).catch((err) => {
// this.$message({
// message: err.message || "更新错误",
// type: "error",
// });
// });