之前已经有一篇关于ts+axios的封装方法,但是那个封装不是利用纯ts方法封装的,略带有点瑕疵。仅用此文补充和参考,如果用ts文件,强烈建议用此文章封装方法。反之用js+axios即可。
通过本文你将学到:
typescript的class类进行封装axios;
ts接口类型判断定义;
get请求参数序列化;
axios.CancelToken取消重复请求方法使用;
AxiosRequestConfig和AxiosInstance 类型使用
学会ts类实现接口方法;
具体实验步骤:
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { ElMessage } from 'element-plus';
// 接口类型和方法
interface BaseType{
baseURL:string;
getConfigParams():any;
interceptors(instance:AxiosInstance, url: string | number | undefined):any;
request(options: AxiosRequestConfig):any;
}
interface AxiosRequestType {
baseURL?: string;
url?: string|undefined;
data?: any;
params?: any;
method?: string;
headers?: any;
timeout?: number;
value?: any
cancelToken?: any
}
// 取消重复请求
const CancelToken = axios.CancelToken
// 用于存储每个请求的取消函数以及对应标识
let sources:any = []
// 取消函数
let removeSource = (config:any)=>{
for(let item in sources){
if(sources[item].umet === config.url+"&"+config.method){
sources[item].cancel('已取消重复请求,请勿重复请求')
sources.splice(item, 1)
}
}
}
class AxiosHttpRequest implements BaseType{
baseURL: string;
timeout: number;
constructor(){
this.baseURL = import.meta.env.VITE_APP_BASE_API
this.timeout = 1500
}
// 配置参数
getConfigParams(){
const config = {
baseURL: this.baseURL,
timeout: this.timeout,
headers:{}
}
return config;
}
// 拦截设置
interceptors(instance:AxiosInstance, url: string | number | undefined){
// 请求拦截
instance.interceptors.request.use((config: AxiosRequestType) =>{
// 取消重复请求
removeSource(config)
config.cancelToken = new CancelToken(c =>{
// 将取消函数存起来
sources.push({ umet: config.url+'&'+config.method, cancel: c })
})
// 添加全局的loading..
// 请求头携带token
// config.headers['Authorization'] = 'Bearer ' + 'token666'
config.headers['Content-Type'] = 'application/json;charset=utf-8'
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?';
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof(value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
return config
}, (error:any)=>{
return Promise.reject(error)
})
// 响应拦截
instance.interceptors.response.use((res:any) =>{
// 取消重复请求
removeSource(res.config)
// 未设置状态码则默认成功状态
const code = res.data['code'] || 200;
// 获取错误信息
let msg = res.data['msg'] || ""
switch (code) {
case "401":
msg = '认证失败,无法访问系统资源'
break;
case "403":
msg = '当前操作没有权限'
break;
case "404":
msg = '访问资源不存在'
break;
case "default":
msg = '系统未知错误,请反馈给管理员'
break;
default:
return '未知错误,请联系管理员'
}
if(code === 200){
return Promise.resolve(res.data)
}else{
ElMessage.error(msg)
return Promise.reject(res.data)
}
}, (error:any) =>{
console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
}
else if (message.includes("timeout")) {
message = "系统接口请求超时";
}
else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
ElMessage.error({
message: message,
duration: 5 * 1000
})
return Promise.reject(error)
})
}
/**
* 外部调用方法
* @param options axios请求参数
* @returns 实例
*/
request(options: AxiosRequestConfig){
const instance = axios.create();
options = Object.assign(this.getConfigParams(), options)
this.interceptors(instance, options.url)
return instance(options)
}
}
// 实例化请求类
const http = new AxiosHttpRequest();
export default http;
import http from "@/script/utils/http";
export const getArticleList = (data:object) =>{
return http.request({
url: '/app/blog/article/page',
method: 'POST',
data
})
}
<script lang="ts" setup>
import {onMounted} from "vue";
import { getArticleList } from "@/script/api/article";
import PageParams from '@/script/utils/page-params';
const pageParam = reactive<PageParams>({
pageNum: 1,
pageSize: 10
})
onMounted(()=>{
getArticleList(pageParam).then(res=>{
console.log(res);
})
})
</script> 备注:具体response响应回调判断要根据自己服务接口返回类型判断。这里我是以我的服务器响应数据格式为案例的。