当前位置: 首页 > Web前端 > vue.js

Vue3+Tspackageaxios

时间:2023-03-31 21:25:31 vue.js

packageideaindex.ts我们需要在src根目录下新建一个axios文件夹,在里面新建一个index.ts文件。该文件主要用于封装axios的配置(实例化请求配置、Request拦截器、对应的拦截器)和对应的方法(登录跳转、消息提示、错误处理等)base.ts该文件主要用于项目扩展时不同的模块需要调用不同的接口(请求基址baseURL)前期做好的准备工作,方便后期维护。request.ts主要用于封装基于axios配置的get/post/put/delete等使用方法。api.ts后面在main.ts中引入这个模块,包括将所有的接口数据信息写入到这个文件中。index.ts包如下。考虑到职责单一,index只封装了axios//index.tsimportaxios,{AxiosRequestConfig,Method}from"axios";importrouterfrom"@/router";importstorefrom"@/store";import{message}from'ant-design-vue'import{storage}from"../storage/storage";import{dataList}from"@/components/aspin/data";/***跳转到登录页面*携带当前页面route,为了登录页面完成登录后返回当前页面*/consttoLogin=()=>{router.replace({name:'LoginPage',});}/***统一错误处理后请求失败*@param{Number}status请求失败的状态码*/consterrorHandle=(status:number,other:string)=>{//状态码判断switch(status){case302:message.error('界面被重定向了!');休息;case400:message.error("发送的请求有错误,服务器没有创建或修改数据==>"+status)break;//401:Notloggedin//如果没有登录则跳转到登录页面,并携带当前页面的路径//登录成功后返回当前页面,此步骤需要在登录页面进行操作。case401://redirectmessage.error("token:loginfailure==>"+status+":"+store.state.Roles)storage.remove(store.state.Roles)storage.get(store.state.角色)router.replace({path:'/Login',});休息;//403tokenexpired//清除token并跳转到登录页面case403:message.error("登录过期,用户已授权,但禁止访问==>"+status)//store.commit('token',无效的);setTimeout(()=>{router.replace({path:'/Login',});},1000);休息;case404:message.error("网络请求不存在==>"+status)break;case406:message.error("请求格式不可用==>"+status)break;case408:message.error("请求超时!")break;case410:message.error("请求的资源被永久删除,不会再获取==>"+status)break;case422:message.error("创建对象时,校验错误==>"+status)break;case500:message.error("服务器发生错误,请检查服务器==>"+status)break;案例502:我ssage.error("网关错误==>"+status)break;case503:message.error("服务不可用,服务器暂时过载或维护中==>"+status)break;case504:message.error("网关超时==>"+status)break;default:message.error("Othererrors==>"+status)}}//定义接口interfacePendingType{url?:string;方法?:方法;参数:任何;数据:任何;cancel:any;}//取消重复请求constpending:Array=[];constCancelToken=axios.CancelToken;//移除重复请求constremovePending=(config:AxiosRequestConfig)=>{for(constkeyinpending){constitem:number=+key;常量列表:PendingType=pending[key];//当数组中存在当前请求时执行函数体if(list.url===config.url&&list.method===config.method&&JSON.stringify(list.params)===JSON.stringify(config.params)&&JSON.stringify(list.data)===JSON.stringify(config.data)){//执行取消list.cancel('操作过于频繁,请稍后再试');//从数组中移除记录pending.splice(item,1);}}};/*实例化请求配置*/constinstance=axios.create({headers:{//php的posttransmission请求头必须是这个,否则会报错收不到值"Content-Type":"application/json;charset=UTF-8","Access-Control-Allow-Origin-Type":'*'},//请求时长timeout:1000*30,//请求基地址TODO:这个block会根据不同进行调整未来模块不同的apibaseURL:process.env.VUE_APP_API_URL,//?"Test"//:"Official",//表示跨域请求是否需要凭据withCredentials:false,})/***requestinterceptor*per在第二次请求之前,如果有token,则在请求头中携带token*/instance.interceptors.request.use(config=>{removePending(config);config.cancelToken=newCancelToken((c)=>{pending.push({url:config.url,method:config.method,params:config.params,data:config.data,cancel:c});});//在登录流程控制中,判断使用r的登录根据本地是否有token情况//但是即使token存在,token也可能过期,所以在每个请求头中携带token//后台根据携带的token判断用户的登录状态,并返回给我们相应的状态码//然后我们在响应拦截器中,可以根据状态码进行一些统一的操作//consttoken=store.state.token;//localStorage.setItem('token',token);如果(storage.get(store.state.Roles)){store.state.Rolesconfig.headers.Authorization=storage.get(store.state.Roles);}返回配置;},error=>{message.error(error.data.error.message);返回Promise.reject(error.data.error.message);})//响应拦截器instance.interceptors.response.use(function(config){dataList.show=trueremovePending(config.config);//请求成功if(config.status===200||config.status===204){setTimeout(()=>{dataList.show=false},400)returnPromise.resolve(config);}else{returnPromise.reject(config);}//请求失败},function(error){const{response}=error;if(response){errorHandle(response.status,response.data.message);//超时重新请求constconfig=error.config;//全局请求次数,请求间隙const[RETRY_COUNT,RETRY_DELAY]=[3,1000];如果(配置&&RETRY_COUNT){//设置用于跟踪重试计数的变量config.__retryCount=config.__retryCount||0;//检查总重试次数是否用完if(config.__retryCount>=RETRY_COUNT){returnPromise.拒绝(响应||{消息:错误。消息});}//增加重试次数config.__retryCount++;//创建新的Promise来处理指数退避constbackoff=newPromise((resolve)=>{setTimeout(()=>{resolve();},RETRY_DELAY||1);});//Promisereturnbackoff.then(()=>{returninstance(config);});}返回Promise.reject(响应);}else{//处理断线情况//eg:当请求超时或断线时,更新state的网络状态//网络状态控制app.vue中全局断线的显示和隐藏提示组件//后续增加一些断网时的操作每个模块的baseUrl方便后期维护管理//base.tsexportclassBase{/*publicmodule*/staticenv=process.env.NODE_ENV==="development"?“http://localhost:8087":"https://produceCommon.com(产线地址)"}也可以直接在index.ts中设置这样base.tsconstinstance=axios.create({//请求的base地址TODO:在这块之后,会根据不同的模块调整不同的apibaseURLs:process.env.VUE_APP_API_URL,})需要配置根目录env.developmentNODE_ENV='development'#VUE_APP_API_URL='https://localhost:5001/'VUE_APP_API_URL='http://localhost:8087/'.env.production#生产环境请求接口NODE_ENV='production'VUE_APP_API_URL='http://129.xxxxx/'request.ts封装了get和post方法axios的,其他关于接口调用的方法也可以写到这个文件中,方便管理//request.tsimportaxiosfrom"./index";importqsfrom"qs";exportclassRequest{/***getmethod*@param{string}urlpath*@param{object}paramsparameter*/staticget=(url:string,params?:any)=>{returnnewPromise((resolve,reject)=>{axios.get(url,{params:params}).then(res=>{resolve(res);}).catch(err=>{reject(err);})})}staticpost=(url:string,params?:any)=>{returnnewPromise((resolve,reject)=>{axios.post(url,qs.stringify(params)).then(res=>{resolve(res);}).catch(err=>{reject(err);})})}}api.tsvue页面需要使用api接口//使用install的目的是main.ts中的ts//不能通过Vue.prototype.$Api直接调用//在全局方法中,会说使用插件方式挂载.//api.tsimport{Base}from"./base";import{Request}from"./request";classapi{/*api接口模块*/publicstaticarticle={//直接在index.ts中设置Basemodulegenre不需要:()=>Request.get('/api/SnArticle/GetCountAsync'),//根据Base模块封装调用genres:()=>Request.get(`${Base.env}/api/SnArticle/GetCountAsync`),}}export{api}index.vueimport{api}from'../../utils/api/api'import{onMounted}from'vue'onMounted(async()=>{awaitQueryAll()api.article.genre().then((res:any)=>{console.log('genre'+res.data)})api.article.genres().then((res:any)=>{console.log('genres'+res.data)})})参考https://blog.csdn.net/qq_4003...