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

封装axios

时间:2023-03-31 15:52:05 vue.js

前言axios是一个轻量级的HTTP客户端,它基于XMLHttpRequest服务执行HTTP请求,支持丰富的配置,支持Promise,支持浏览器和Node.js。从Vue2.0开始,游达(游禹锡,Vue作者)宣布取消官方对vue-resource的推荐,转而推荐axios。现在axios已经成为大部分Vue开发者的首选。(如果你还不熟悉axios,你可以在这里查看它的API)。axios的API非常友好,你可以很方便的直接在你的项目中使用。但是随着项目规模的增大,每次发起HTTP请求,都必须进行设置超时时间、设置请求头、根据项目环境判断使用哪个请求地址、错误处理等操作写在现场。疯狂的!这种重复劳动不仅浪费时间,而且使代码冗余,难以维护。为了提高我们的代码质量,在使用前应该在项目中重新封装axios。那么,如何封装axios呢?封装前的原貌我们先看一下axios请求在一个实际项目中没有封装的情况下的原貌。它看起来像这样:axios('http://localhost:3000/data',{method:'GET',timeout:1000,withCredentials:true,headers:{'Content-Type':'application/json',Authorization:'xxx',},transformRequest:[function(data,headers){returndata;}],//其他请求配置...}).then((data)=>{//todo:真正的业务逻辑代码console.log(data);},(err)=>{if(err.response.status===401){//处理授权错误}if(err.response.status===403){//处理serverforbiddenerror}//其他错误处理...console.log(err);});可以看到这段代码中,页面代码逻辑只在第15行,上面一大块请求配置代码和下面一大块响应错误处理代码,和页面功能几乎没有关系,而且这些内容每个请求都相似,有些部分甚至完全相同。试想一下,每次发请求都这样,写了十几个请求,会是怎样的盛况呢?封装步骤封装的本质就是在要封装的内容之外添加各种东西,然后将它们作为一个新的整体呈现给用户,以达到扩展和易用的目的。封装axios的时候要做的事情就是提前在axios上配置所有HTTP请求的通用配置,保留必要的参数和接口,然后作为一个新的axios返回。接下来我们用一个demo来实现一个扩展性很好的axios包。demo目录结构如下(Vue-cli3.0生成):|--public/|--mock/||--db.json#我的新界面模拟数据|--src/||--资产/||--组件/||--路由器/||--商店/||--观点/||--首页.Vue||--App.vue||--main.js||--theme.styl|--package.json|...打包目标希望在Home页面,发起axios请求的时候像调用方法一样简单,只有几个参数,这样我就可以专注于业务代码。1.将axios封装成一个单独的文件在src下创建一个utils/http.js文件cdsrcmkdirutilstouchhttp.jsimportaxios//src/utils/http.jsimportaxiosfrom'axios';创建一个类也可以用Function来封装,我只是觉得类更语义化。//src/utils/http.js//...classNewAxios{}为不同的环境配置不同的请求地址根据process.env.NODE_ENV配置不同的baseURL,使得项目在不同的环境下执行相应的即可打包命令自动切换请求主机地址。//src/utils/http.js//...constgetBaseUrl=(env)=>{letbase={production:'/',development:'http://localhost:3000',test:'http://localhost:3001',}[环境];如果(!base){base='/';}returnbase;};classNewAxios{constructor(){this.baseURL=getBaseUrl(process.env.NODE_ENV);}}配置超时时间的timeout属性,我一般设置为10秒。//src/utils/http.js//...classNewAxios{constructor(){//...this.timeout=10000;}}配置允许携带凭据widthCredentials属性设置为true。//src/utils/http.js//...classNewAxios{constructor(){//...this.withCredentials=true;}}为该类创建一个实例方法request在request方法中,新建一个axios实例,接收请求配置参数,处理参数,添加配置,返回axios实例(一个promise对象)的请求结果。也可以不创建直接使用默认导出的axios实例,然后把所有的配置都放在上面,但是这样整个项目会共享一个axios实例。虽然这对于大多数项目来说已经足够了,但是在某些项目中不同服务地址的请求和响应结构可能完全不同。这个时候共享单实例是支持不了的。所以为了让封装更加通用和灵活,我会使用axios的create方法,让每个请求都成为一个新的axios实例。//src/utils/http.js//...classNewAxios{//...request(options){//每个请求都会创建一个新的axios实例。常量实例=axios.create();constconfig={//将用户传递的参数与公共配置合并。...选项,baseURL:this.baseURL,超时:this.timeout,withCredentials:this.withCredentials,};//配置拦截器,支持根据不同的url使用不同的拦截器。this.setInterceptors(实例,options.url);返回实例(配置);//返回axios实例的执行结果}}因为拦截器的配置内容比较多,所以封装成一个内部函数。配置请求拦截器在发送请求之前对请求参数所做的所有修改都统一配置在这里。比如统一添加token证书,统一设置语言,统一设置内容类型,指定数据格式等等。完成后记得返回此配置,否则整个请求将无法通过。我将在这里配置一个令牌。//src/utils/http.js//...classNewAxios{//...//这里的url允许你为需要特殊处理的接口路径设置不同的拦截器。setInterceptors=(instance,url)=>{instance.interceptors.request.use((config)=>{//请求拦截器//配置tokenconfig.headers.AuthorizationToken=localStorage.getItem('AuthorizationToken')||'';返回配置;},err=>Promise.reject(err));}//...}配置响应拦截器以在请求的then或catch处理之前预处理响应数据。比如过滤响应数据等等,就是在这里对各种响应错误码进行统一的错误处理,以及断线处理等等。我这里先判断403和断线。//src/utils/http.js//...classNewAxios{//...setInterceptors=(instance,url)=>{//...instance.interceptors.response.use((response)=>{//ResponseInterceptor//todo:如果要根据业务需要对响应结果进行预处理,放在这里console.log();returnresponse;},(err)=>{if(err.response){//响应错误码处理switch(err.response.status){case'403'://todo:handlerserverforbiddenerrorbreak;//todo:handlerotherstatuscodedefault:break;}returnPromise.reject(err.response);}if(!window.navigator.online){//断线处理//todo:跳转到离线页面return-1;}returnPromise.reject(err);});}//...}另外,在拦截器中,也适合放置加载等缓冲效果:在请求拦截器中显示加载,在响应拦截器中移除加载。这样所有的请求都有一个统一的加载效果。默认导出新实例//src/utils/http.js//...exportdefaultnewNewAxios();最终完整代码如下://src/utils/http.jsimportaxiosfrom'axios';constgetBaseUrl=(env)=>{letbase={production:'/',development:'http://localhost:3000',test:'http://localhost:3001',}[env];如果(!base){base='/';}returnbase;};classNewAxios{constructor(){this.baseURL=getBaseUrl(process.env.NODE_ENV);这个。超时=10000;this.withCredentials=true;}setInterceptors=(instance,url)=>{instance.interceptors.request.use((config)=>{//在此处添加加载//配置令牌config.headers.AuthorizationToken=localStorage.getItem('AuthorizationToken')||'';返回配置;},err=>Promise.reject(err));instance.interceptors.response.use((response)=>{//此处去掉加载//todo:我想根据业务需要对响应结果进行预处理},(err)=>{if(err.response){//响应错误码处理开关(err.response.status){case'403'://todo:handlerserverforbiddenerrorbreak;//todo:handler其他状态码default:break;}返回Promise.reject(err.response);}if(!window.navigator.online){//断线处理//todo:跳转到离线页面return-1;}返回Promise.reject(err);});}request(options){//每个请求都会创建一个新的axios实例constinstance=axios.create();constconfig={//将用户传递的参数与公共配置合并。...选项,baseURL:this.baseURL,超时:this.timeout,withCredentials:this.withCredentials,};//配置拦截器,支持根据不同的url使用不同的拦截器。this.setInterceptors(实例,options.url);返回实例(配置);//返回axios实例的执行结果}}exportdefaultnewNewAxios();现在axios包已经完成了80%。我们还需要进一步将axios和接口结合起来,再封装一层,达到我一开始定下的封装目标。2.使用新的axios包API,在src目录下新建api文件夹。将所有涉及HTTP请求的接口集中到该目录下进行管理。创建一个新的home.js。我们需要将界面按照一定的规则进行分类,一类界面对应一个js文件。这种分类可以按页面划分,也可以按模块划分等等。为了更直观的演示,我这里分页进行。实际上,这取决于您的需求。使用新的axios包API(固定url值,合并用户传递的参数),然后命名并导出这些函数。//src/api/home.jsimportaxiosfrom'@/utils/http';exportconstfetchData=options=>axios.request({...options,url:'/data',});exportdefault{};在api目录下新建index.js,将其他文件的接口汇总导出到该文件中。//src/api/index.jsexport*from'./home';这层封装将我们新建的axios封装成更加??简洁语义化的接口方法。现在我们的目录结构如下所示:|--public/|--mock/||--db.json#接口模拟数据|--src/||--api/#所有接口都集中在这个目录下|--home.js#首页涉及的接口都封装在这里||--index.js#项目中所有接口调用的入口||--资产/||--组件/||--路由器/||--商店/||--效用/||--http.js#这里是axios包||--观点/||--首页.Vue||--App.vue||--主要.js||--theme.styl|--package.json|...使用封装好的axios现在我们要发送HTTP请求的时候只要导入api下的index.js文件就可以调用任何接口,而封装好的axios用来。//src/views/Home.vueaxios请求封装在fetchData函数中,页面请求完全不需要任何axiosAPI。静默发出请求并获得响应就像调用简单的Promise函数一样简单。而你只需要专注于处理页面上的业务功能,而不会被其他事情打扰。运行npmrunserve启动项目,执行npmrunmock启动servicemock接口。现在打开localhost:8080可以看到主页。打开浏览器控制台,可以看到打印出来的请求响应结果:简洁大方。总结封装的思想是前端技术中一个非常有用的思想。简单的axios和接口封装就可以让我们领略到它的魅力。axios的封装没有绝对的标准,只要你的封装能够满足你的项目需求,并且简单易用,就是很好的封装方案。BTW:上面的封装为你提供了一个封装好的axios和api框架。经过以上过程,打包好的axios就不仅仅局限于Vue了。React项目也可以使用,适用于任何前端项目。本文代码可在此获取:https://github.com/yc111/wrap...欢迎交流~欢迎转载,转载请注明出处:https://champyin.com/2019/12/...