1 请求拦截器介绍
拦截器的作用:用于我们在网络请求的时候发起请求或者响应请求时对操作进行响应的处理。
比如: 发起请求时候可以添加加载动画、token认证强制登陆等;
响应时候进行数据处理
1.1 基本的请求拦截器
axios.interceptors.request.use(config=>{
console.log("进入请求拦截器")
return config;//放行请求 *
//config包含data、headers、request、status、statusText
},err=>{
console.log("请求失败")
})
1.2 基本的响应拦截器
axios.interceptors.response.use(config=>{
console.log("响应拦截器")
//进行拦截操作
return config;//放行
},err=>{
console.log("响应失败")
})
项目中的模板
2 vue+vant(轻提示)
其他知识(定义开发环境以及生产环境的地址):
在根目录下定义.env.production文件来存放生产环境地址
# 配置生产地址,就是你将来发布上线的地址
VUE_APP_URL="http://xxx.xxx.xx.xx:3000"
在根目录下定义.env.development文件来存放生产环境地址
VUE_APP_URL="xxxxxxxxx"
src下创建api/index.js配置拦截
import axios from "axios";
import Vue from "vue";
import { Dialog } from 'vant';
//配置的地址文件
import '../../.env.development'
// vant提供的轻提示组件
import { Toast } from "vant";
Vue.use(Toast);
import store from '@/store/index'
//可以选择使用直接定义的方式,也可以选择导入地址文件的方式(建议真实项目中用导入地址文件的方式)
// let env = "prod";//prod生产环境,dev开发环境
// let baseURL = '';
// if (env === 'dev') {
// baseURL = 'http://xxx.xxx.xx.xx:3000';
// } else {
// baseURL = 'http://xxx.xxx.xx.xx:3000';
// }
//导入地址文件的方式
console.log("开发环境",process.env.NODE_ENV);//开发环境,开发状态下是development
console.log("当前开发环境基础地址",VUE_APP_URL)
const service = axios.create({
// 配置基本路径
baseURL:VUE_APP_URL,
timeout: 50000, // 请求超时时间(因为需要调试后台,所以设置得比较大)
});
// request 对请求进行拦截
service.interceptors.request.use(
(config) => {
if (config.method === "get") {
if (config.params) {
//对于get请求
if (!config.params.noLoading) {
// 开启loading
Toast.loading({
message: "加载中...",
forbidClick: true,
loadingType: "spinner",
});
} else {
delete config.params.noLoading;
}
}
}
// 请求头添加token
//前提是使用了vuex配置了store
config.headers["user-token"] = store.state.token;
return config;
},
(error) => {
Promise.reject(error);
}
);
// response 响应拦截器
service.interceptors.response.use(
(response) => {
// 清除loading
Toast.clear();
const res = response.data;
if (res.code == 666) {
return res;
} else if (res.code == 603) {
Dialog.confirm({
title: '温馨提示',
message: '您还未登录,是否去登录',
})
.then(() => {
// on confirm
})
.catch(() => {
// on cancel
});
} else {
// 成功连接到后台, 但是没有返回正确的数据
Toast.fail(res.msg);
}
},
(error) => {
Toast.clear();
// 跟后台连接失败
Toast.fail("网络异常,请稍后再试");
}
);
export default service;
3 vue + elementUi
import axios from "axios";
import {
ElLoading,
ElMessage
} from 'element-plus'
let isDev = process.env.NODE_ENV === "development";
// isDev = false;
let baseURL;
if (isDev) {
baseURL = "xxx.xxx.xxx.xx:3000";
} else {
baseURL = "xxx.xxx.xxx.xx:3000";
}
const service = axios.create({
baseURL,
timeout: 30000, // 请求超时时间(因为需要调试后台,所以设置得比较大)
});
let loadObj;
// request拦截器
service.interceptors.request.use(
(config) => {
if (!loadObj) {
loadObj = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
}
return config;
},
(error) => {
setTimeout(() => {
loadObj.close();
}, 300);
return Promise.reject(error);
}
);
// response 拦截器
service.interceptors.response.use(
(response) => {
setTimeout(() => {
loadObj.close();
}, 300);
const res = response.data;
if (res.code == 666) {
return res;
} else {
ElMessage(res.msg);
return Promise.reject(res.msg);
}
},
(error) => {
setTimeout(() => {
loadObj.close();
}, 300);
ElMessage(error.message);
return Promise.reject(error.message);
}
);
export default service;
4 react + antdMobile ui
import axios from "axios";
import { Toast, Dialog } from 'antd-mobile'
import React from 'react';
let isProd = process.env.NODE_ENV === "production";
let baseURL;
if (isProd) {
baseURL = "xxx.xxx.xxx.xx:3000";
} else {
baseURL = "xxx.xxx.xxx.xx:3000";
}
const service = axios.create({
baseURL,
timeout: 10 * 60 * 1000,
});
//4. 请求拦截
service.interceptors.request.use(
(config) => {
// config.headers["Content-Type"] = 'application/json;charset=utf-8'
Toast.show({
icon: 'loading',
content: '加载中…',
})
if (localStorage.getItem('token')) {
config.headers["user-token"] = localStorage.getItem('token')
} else {
config.headers["user-token"] = ''
}
// do something
return config;
},
(err) => {
return Promise.reject(err);
}
);
service.interceptors.response.use(
(res) => {
Toast.clear();
if (res.data.code === 603) {
Dialog.confirm({
content: '您还未登录,是否前去登录',
onConfirm: () => {
Toast.show({ content: '点击了确认', position: 'bottom' })
location.href = 'http://localhost:3000/login'
},
onCancel: () => {
Toast.show({ content: '取消', position: 'bottom' })
}
})
}
if (res.data.code !== 666) {
return Promise.reject(res.data.msg);
}
return res;
},
(err) => {
Toast.show({
icon: 'fail',
content: '加载失败',
})
return Promise.reject(err);
}
);
export default service;
5 ts+react 项目request进行验证
import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
type Result= {
code: number|string;
msg: string;
currPage?:number|string;
pageSize?:number|string;
total?:number;
result: any;
};
class Request {
// axios 实例
instance: AxiosInstance;
// 基础配置,url和超时时间
baseConfig: AxiosRequestConfig = { baseURL: "http://xxx.xxx.xx.xx:3000", timeout: 60000 };
constructor(config: AxiosRequestConfig) {
// 使用axios.create创建axios实例
this.instance = axios.create(Object.assign(this.baseConfig, config));
// 请求拦截器
this.instance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 一般会请求拦截里面加token
// const token = localStorage.getItem("token");
config.headers = { 'user-token': "token值" };
return config;
},
(err: any) => {
return Promise.reject(err);
}
);
// 响应拦截器
this.instance.interceptors.response.use(
(res) => {
// 直接返回res,当然你也可以只返回res.data
return res.data;
},
(err: any) => {
// 这里用来处理http常见错误,进行全局提示
let message = "";
switch (err.response.status) {
case 400:
message = "请求错误(400)";
break;
case 401:
message = "未授权,请重新登录(401)";
// 这里可以做清空storage并跳转到登录页的操作
break;
case 403:
message = "拒绝访问(403)";
break;
case 404:
message = "请求出错(404)";
break;
case 408:
message = "请求超时(408)";
break;
case 500:
message = "服务器错误(500)";
break;
case 501:
message = "服务未实现(501)";
break;
case 502:
message = "网络错误(502)";
break;
case 503:
message = "服务不可用(503)";
break;
case 504:
message = "网络超时(504)";
break;
case 505:
message = "HTTP版本不受支持(505)";
break;
default:
message = `连接出错(${err.response.status})!`;
}
// 这里错误消息可以使用全局弹框展示出来
// 比如element plus 可以使用 ElMessage
// ElMessage({
// showClose: true,
// message: `${message},请检查网络或联系管理员!`,
// type: "error",
// });
alert('请检查网络或联系管理员');
// 这里是AxiosError类型,所以一般我们只reject我们需要的响应即可
return Promise.reject(err.response);
}
);
}
// 定义请求方法
public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
return this.instance.request(config);
}
public get<T = any>(
url: string,
config?: AxiosRequestConfig
): Promise<Result> {
return this.instance.get(url, config);
}
public post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<Result> {
return this.instance.post(url, data, config);
}
public put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<Result> {
return this.instance.put(url, data, config);
}
public delete<T = any>(
url: string,
config?: AxiosRequestConfig
): Promise<Result> {
return this.instance.delete(url, config);
}
}
export default Request;