axios的二次封装-vue

23 篇文章 0 订阅

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",
// 	});
// });

参考:https://segmentfault.com/a/1190000016474460

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值