概述
官网
一、安装 axios
npm i -S axios qs
二、axios 请求二次封装
src/api/http.js:
import Vue from 'vue';
import axios from 'axios';
import qs from 'qs';
import router from '../router/index';
let loadingService = null,
loadingRequestQueue = [];
// 默认接口配置
let initConfig = {
isNeedLoading: true, // 是否需要loading
isHideErrorAlert: false, // 是否不显示错误弹窗
};
const instance = axios.create({
timeout: 40000,
});
// post默认请求头设置
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// 请求拦截
instance.interceptors.request.use(
config => {
// console.log('request--->', config);
const { method = 'get' } = config;
// config.headers.TrackId = config.trackId;
// config.headers.CompanyId = 1693;
if (method === 'post') {
if (!config.data) {
config.data = {};
}
if (config.submitType === 'json') {
config.headers['Content-Type'] = 'application/json';
// config.data = JSON.stringify(config.data) // axios内部自动会序列化
} else {
config.data = qs.stringify(config.data);
}
}
return config;
},
error => {
console.log('request error--->', error);
return Promise.reject(error);
}
);
// 响应拦截器
instance.interceptors.response.use(
response => {
// console.log('response--->', response);
if (response.status === 200) {
return Promise.resolve(response);
}
return Promise.reject(response);
},
error => {
// console.log('errorRes---->', error.response);
// console.log('errorMsg---->', error.message);
const Alert = Vue.prototype.$alert;
const { response, message = '' } = error;
// 在这里可以做个收集错误日志操作
if (response && !response.config?.isHideErrorAlert) {
if (message.indexOf('timeout') > -1) {
Alert('请求超时请重试', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
}
if (message.indexOf('Network Error') > -1) {
Alert('网络出错', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
}
switch (response.status) {
case 400:
Alert('400 请求参数有误', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
Alert({
message: '未登录! ',
type: 'warning',
});
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath,
},
});
break;
// 403 登录过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Alert({
message: '登录过期,请重新登录',
type: 'warning',
});
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath,
},
});
}, 1000);
break;
case 404:
Alert(response.config?.url + ' 404 Not Found', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 405:
Alert(response.config?.url + ' 405 请求未被允许', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 500:
Alert('500 服务器异常', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 501:
Alert('501 服务器不支持当前请求', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 502:
Alert('502 网关出错', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 503:
Alert('503 服务不可用', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
case 504:
Alert('504 网关超时', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
default:
Alert('网络出错', '异常信息', {
confirmButtonText: '确定',
type: 'error',
});
break;
}
}
return Promise.reject(error);
}
);
/**
* 判断是否有接口还未加载完
* @param {*} trackId
*/
function compareLoadingStatus(trackId) {
const targetIndex = loadingRequestQueue.findIndex(item => item === trackId);
if (targetIndex > -1) {
loadingRequestQueue.splice(targetIndex, 1);
}
if (!loadingRequestQueue.length) {
loadingService?.close();
}
}
function getTrackId() {
return `trackid${new Date().getTime()}_${(Math.random() * 100000).toFixed(0)}`;
}
// 请求公共函数
function send(method = 'get', url, data = {}, options = {}) {
const Loading = Vue.prototype.$loading;
options = {
...initConfig,
...options,
trackId: getTrackId(),
};
if (options.isNeedLoading) {
loadingRequestQueue.push(options.trackId);
if (!loadingService) {
loadingService = Loading?.({
fullscreen: true,
background: 'transparent',
});
}
}
return new Promise((resolve, reject) => {
instance({
method,
url,
[method === 'get' ? 'params' : 'data']: data,
...options,
})
.then(res => {
resolve(res.data);
})
.catch(error => {
reject(error);
})
.finally(() => {
if (options.isNeedLoading) {
compareLoadingStatus(options.trackId);
}
});
});
}
/**
* 封装get请求
*/
export function get(url, params = {}, options = {}) {
return send('get', url, params, options);
}
/**
* 封装post请求
*/
export function post(url, data = {}, options = {}) {
return send('post', url, data, options);
}
Loading 和 Alert 用的是 element-ui 的。
options 可选参数:
- isNeedLoading: boolean 是否需要loading
- isHideErrorAlert: boolean 请求错误时是否关闭默认的错误提示弹窗
- submitType: string,值为 json,请求参数会用 json 格式
- axios 规定的请求配置,如 timeout、withCredentials 等
特有功能:
- 同时发起多个请求时,所有请求结束后才关闭 loading。
请求 headers 里的 Content-Type 可以不用设置,axios 会根据传入的 data 参数的格式自动设置 Content-Type:
data参数格式 | Content-Type |
---|---|
"name=jim&age=22" 这种序列化过的格式 | application/x-www-form-urlencoded |
普通对象 | application/json |
三、接口管理
api接口管理的一个好处就是,我们把api统一集中起来,如果后期需要修改接口,我们就直接在api.js中找到对应的修改就好了,而不用去每一个页面查找我们的接口然后再修改会很麻烦。关键是,万一修改的量比较大,就gg了。还有就是如果直接在我们的业务代码修改接口,一不小心还容易动到我们的业务代码造成不必要的麻烦。
// api.js
import { get, post } from './http'
export const apiAddress = parmas => post('api/v1/users/info', parmas);
四、axios-retry —— 接口重试插件
让你的 axios 支持自动重试的功能。文档
import axios from 'axios';
import axiosRetry from 'axios-retry';
axiosRetry(axios, { retries: 3 });
axios.get('http://example.com/test') // The first request fails and the second returns 'ok'
.then(result => {
result.data; // 'ok'
});
最后
以上就是专注导师为你收集整理的axios 请求封装的全部内容,希望文章能够帮你解决axios 请求封装所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复