ajax网站,潍坊专升本教育机构,百度一下电脑版网页,wordpress 不同面包屑TypeScript封装Axios 
Axios的基本使用 
因axios基础使用十分简单#xff0c;可参考axios官方文档#xff0c;这里不在介绍他基本用法#xff0c;主要讲解拦截器。 拦截器主要分为两种#xff0c;请求拦截器和响应拦截器。 请求拦截器#xff1a;请求发送之前进行拦截可参考axios官方文档这里不在介绍他基本用法主要讲解拦截器。 拦截器主要分为两种请求拦截器和响应拦截器。 请求拦截器请求发送之前进行拦截应用于我们在请求发送前需要对请求数据做一些处理。例如 携带token当请求时间过长时设置loading 响应拦截器在响应到达时进行拦截应用于在我们业务代码中拿到数据之前需要对数据做一定处理。例如 转换数据格式移除loading 为什么要封装Axios 
在项目中会有很多的模块都需要发送网络请求常见的比如登录模块首页模块等如果我们项目中直接使用诸如axios.get(), axios.post()会存在很多弊端哪些弊端呢 首先这样做会导致我们每个模块对axios依赖性太强意味着我们项目中的每个模块都和一个第三方库耦合度较高这样的话如果axios不在维护我们要更换库的时候将非常麻烦我们可以假设一下随着时间的推移axios可能因为浏览器的升级Webpack的改变而出现一些bug 然而axios已不再维护这时我们往往需要切换库这就意味着我们需要去修改每个模块中的请求相关的代码显而易见非常繁琐。还有一点在我们发送网络请求的时候往往会有很多共同的特性比如说在我们成功登录之后的其他请求中我们往往需要在请求头中添加token然后发送请求在每次请求中我们想展示一个loading… 这些功能如果在每次请求的逻辑中都写一遍很明显我们的代码重复度太高了。 而axios封装之后则会带来很多好处 解决以上弊端降低与第三方库的耦合度这样我们将来需要更换库时只需要修改我们封装后的request即可这样我们往往只是修改封装后一两个文件而不再需要每个模块每个模块的修改。 在我们开发中我认为class的相关语法封装性会更好因此这里我选择尝试用类相关的概念来封装axios。我想要的封装后达到的效果可以直接在其他项目使用。 
利用面向对象的思想对Axios进行封装 
基础封装 
封装一个Request的类使得在外部可以调用此类的构造函数创建实例创建的实例就对应axios实例http/request.ts中代码如下 
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from axios;// 创建这个类的目的每个创建出的HDRequest的实例都对应一个axios实例
class Request {// 创建实例的方法constructor()构造实例instance: AxiosInstance;constructor(config: AxiosRequestConfig) {this.instance  axios.create(config);}// 二次封装网络请求的方法request(config: AxiosRequestConfig) {return this.instance.request(config);}
}
// 暴露Request类
export default Request; 
基本配置信息单独写在一个文件中config/index.ts中代码如下 
const CONFIG  {// 服务器地址serverAddress: https://91huajian.cn,// 其他基础配置项入最长响应时间等
};
export default CONFIG;在http/index.ts中创建一个Request类的一个实例http并配置这个实例 
import Request from ./index;
import CONFIG from /config;// 创建一个axios实例
const http  new Request({baseURL: CONFIG.serverAddress,timeout: CONFIG.maxTimeout,
})export default http;在接口中使用该实例发送请求 
// 在http/api/sponsor.ts文件中封装发送请求的方法在页面组件任意位置随意调用
import http from ../request;
// 查询赞助
export const getSponsorListAsync: any  (params: any)  { return http.request({url: /huajian/common/getSponsorList,method: get,params: params});
}拦截器的类型 
拦截器分为三种 类拦截器在封装的axios类文中类为Request类上定义的拦截器实例拦截器在利用Request类实例化对象时传递的参数中定义的拦截器接口拦截器在调用实例时传入的参数中定义的参数 配置全局拦截器类拦截 
保证每一个axios实例对象都有拦截器即本使用Request实例化的对象发送的请求都会被配置的拦截器所拦截并执行拦截器中的程序。 
类拦截器比较容易实现只需要在类中对axios.create()创建的实例调用interceptors下的两个拦截器即可实例代码如下 
import axios, { AxiosInstance,AxiosRequestConfig,AxiosResponse } from axios;
import { RequestConfig } from ./types/types;
class Request {instance: AxiosInstance;constructor(config: RequestConfig) { this.instance  axios.create(config);// 添加全局请求拦截器每个实例都有this.instance.interceptors.request.use(// 拦截到请求中携带的所有配置项config(config: AxiosRequestConfig)  {console.log(全局请求拦截器, config);return config;},(err: any)  err)// 添加全局响应拦截器每个实例都有this.instance.interceptors.response.use(// 拦截到服务器返回的响应体res(res: AxiosResponse)  {console.log(全局响应拦截器, res);return res.data;},(err: any)  err;}request(config: AxiosRequestConfig) { return this.instance.request(config);}
}
export default Request;我们在这里对响应拦截器做了一个简单的处理就是将请求结果中的.data进行返回因为我们对接口请求的数据主要是存在在.data中跟data同级的属性我们基本是不需要的。 
为某一Request实例单独配置拦截器实例拦截 
实例拦截器是为了保证封装的灵活性因为每一个实例中的拦截后处理的操作可能是不一样的所以在定义实例时允许我们传入拦截器。 
新创建一个实例http2在它的config中传入拦截器属性但是axios的AxiosRequestConfig类型中并没有拦截器属性类型。 
因此需要对types/index.ts中的构造函数中的config类型进行扩展extends。首先我们定义一下interface方便类型提示代码如下 
import { AxiosRequestConfig, AxiosResponse } from axios;
// 拦截器的类型
export interface RequestInterceptorsT {// 请求拦截器requestInterceptor?: (config: AxiosRequestConfig)  AxiosRequestConfig;// 在发送请求之前做些什么requestInterceptorCatch?: (error: any)  any;// 对请求错误做些什么// 响应拦截器responseInterceptor?: (res: T)  T;// 对响应数据做点什么responseInterceptorsCatch?: (err: any)  any;// 对响应错误做点什么
}
// 自定义传入的参数
export interface RequestConfigT   AxiosResponse extends AxiosRequestConfig{interceptors?: RequestInterceptorsT;
}然后再创建新的实例并在实例中引入定义的拦截器 
import Request from ./index;
import CONFIG from /config;
import {RequestConfig} from ./types/types;
import { AxiosResponse } from axios;// 创建一个axios实例
const http  new Request({baseURL: CONFIG.serverAddress,timeout: CONFIG.maxTimeout
})
const http2  new Request({baseURL: CONFIG.serverAddress,timeout: CONFIG.maxTimeout,interceptors: {// 配置请求拦截器requestInterceptor: (config: RequestConfig)  { console.log(通过请求拦截器,拿到http2的请求配置参数,config);return config;},// 响应拦截器responseInterceptor: (result: AxiosResponse)  {console.log(通过响应拦截器,拿到http2的响应返回的结果,result);return result;}}
})export default {http,http2};注意这里的拦截器只能由使用http2实例发送的请求才会执行。 
我们的拦截器的执行顺序为实例请求→类请求→实例响应→类响应这样我们就可以在实例拦截上做出一些不同的拦截 
此时在使用Request实例化对象http2时我们传入的配置项中多了interceptors配置项那么在Request类中我们就得接收并在实例化时执行 
import axios, { AxiosInstance,AxiosRequestConfig,AxiosResponse } from axios;
import { RequestConfig,RequestInterceptors } from ./types/types;
class Request {instance: AxiosInstance;// 拦截器对象interceptorsObj?: RequestInterceptorsAxiosResponse;constructor(config: RequestConfig) { this.instance  axios.create(config);this.interceptorsObj  config.interceptors;//接收实例对象传入的该实例的定制拦截器// 全局请求拦截器this.instance.interceptors.request.use((config: AxiosRequestConfig)  {console.log(全局请求成功拦截器, config);return config;},(err: any)  err)  // 使用实例对象的自定义拦截器 针对特定的http2实例添加拦截器this.instance.interceptors.request.use(this.interceptorsObj?.requestInterceptor, // 请求前的拦截器this.interceptorsObj?.requestInterceptorCatch // 发送请求失败的拦截器)// 使用实例对象的自定义拦截器 针对特定的http2实例添加拦截器this.instance.interceptors.response.use(config.interceptors?.responseInterceptor,config.interceptors?.responseInterceptorsCatch);// 全局响应拦截器this.instance.interceptors.response.use((res: AxiosResponse)  {console.log(全局响应成功拦截器, res);return res.data;},(err: any)  {return err;});}request(config: AxiosRequestConfig) { return this.instance.request(config);}
}
export default Request;同一个request实例的不同网络请求设置不同的拦截器接口拦截 
现在我们对单一接口进行拦截操作首先我们将AxiosRequestConfig类型修改为RequestConfig允许传递拦截器然后我们在类拦截器中将接口请求的数据进行了返回也就是说在request()方法中得到的类型就不是AxiosResponse类型了。 
接口中同一个实例在发送不同的request请求时一个配置了拦截器一个没配拦截器 
import { http2 } from ..;http2.request({url: /entire/list,params: {offset: 0,size: 20,},}).then((res)  {console.log(res);});http2.request({url: /home/highscore,interceptors: {responseInterceptor: (config)  {console.log(来自接口定制的请求前的拦截);return config;},responseInterceptor: (res)  {console.log(来自接口的响应成功的拦截);return res;},},}).then((res)  {console.log(res);});对request/index.ts的request方法进行进一步封装使之能够立即执行传进来的拦截器 
// Request类的request方法
// 二次封装网络请求的方法
requestT(config: RequestConfigT): PromiseT { return new Promise((resolve, reject)  {// 为同一个request实例的不同网络请求设置不同的拦截器// 不能将拦截器放在实例上这样的话同一个实例的拦截器都是一样的了// 只能判断传进来的config中是否设置了拦截器若设置了就直接执行// 执行this.instance.request(config)之前先执行requestInterceptor并更新configif (config.interceptors?.requestInterceptor) {//立即调用拦截器函数执行config  config.interceptors.requestInterceptor(config);}// 由于执行完this.instance.request(config)之后才能对response结果进行拦截是个异步的过程// 在Promise内部调用instance实例先执行this.instance.request(config)然后等待结果之后以结果作为拦截器函数的参数进行调用this.instance.requestany, T(config).then((res)  {// 如果给单个响应设置拦截器,这里使用单个响应的拦截器if (config.interceptors?.responseInterceptor) {res  config.interceptors.responseInterceptor(res);}resolve(res);}).catch((err: any)  {reject(err);})})
}各种请求拦截的执行顺序 拦截器执行顺序接口请求 - 实例请求 - 全局请求 - 实例响应 - 全局响应 - 接口响应 实例请求和全局请求的先后顺序取决于在Request类constructor()构造函数中两种请求的执行顺序。 
取消请求 
思路步骤 
创建一个数组用于存储控制器资源在请求拦截器中将控制器存入数组在响应拦截器中将控制器从数组中移除封装一个取消全部请求的方法封住一个可以取消指定请求的方法 
准备 
我们需要将所有请求的取消方法保存到一个集合这里我用的数组也可以使用Map中然后根据具体需要去调用这个集合中的某个取消请求方法。 
因此我们首先进行类型定义 
// 一个取消请求对象键位url值为取消控制器
export interface CancelRequestSource { // 取消请求的标识[index: string]: AbortController;
}然后我们在Request类中定义储存取消请求对象的数组和存放请求url的数组 
/*
存放取消控制对象的集合
* 在创建请求后将取消控制对象 push 到该集合中
* 封装一个方法可以取消请求传入 url: string|string[]  
* 在请求之前判断同一URL是否存在如果存在就取消请求
*/
cancelRequestSourceList ?: CancelRequestSource[];
/*
存放所有请求URL的集合
* 请求之前需要将url push到该集合中
* 请求完毕后将url从集合中删除
* 添加在发送请求之前完成删除在响应之后删除
*/
requestUrlList ?: string[];接着我们要准备两个方法一个时根据url在取消控制对象数组中找到对应请求的方法另一个时完成取消请求后删除存放url数组和存放取下请求对象数组中对象请求的方法。 
//根据url找到取消请求对象数组中此次请求取消对象存放的地址
private getSourceIndex(url: string): number {return this.cancelRequestSourceList?.findIndex((item: CancelRequestSource)  {return Object.keys(item)[0]  url;}) as number;
}
//请求取消完成后我们要删除对应请求和取消请求对象
private delUrl(url: string) {const urlIndex  this.requestUrlList?.findIndex((u)  u  url);const sourceIndex  this.getSourceIndex(url);// 删除url和AbortController对象urlIndex ! -1  this.requestUrlList?.splice(urlIndex as number, 1);sourceIndex ! -1  this.cancelRequestSourceList?.splice(sourceIndex as number, 1);
}在发送请求前存入AbortController对象 
const url  config.url;
// url存在 保存当前请求url 和 取消请求方法
if (url) {this.requestUrlList?.push(url);//将url存入url数组const controller  new AbortController();//构造实例化一个AbortController对象控制器config.signal  controller.signal//绑定请求this.cancelRequestSourceList?.push({[url]: controller//将该控制器添加入cancelRequestSourceList数组})
}请求已经完成了删除保存的url和AbortController对象 
this.instance.requestany, T(config).then(res  {// 如果我们为单个响应设置拦截器这里使用单个响应的拦截器if (config.interceptors?.responseInterceptor) {res  config.interceptors.responseInterceptorT(res)}resolve(res)}).catch((err: any)  {reject(err)}).finally(()  {url  this.delUrl(url);// 请求执行完毕,删除保存在数组中的url和该请求的取消方法});封装取消请求方法 
封装取消全部请求 
// 取消全部请求
cancelAllRequest() {this.cancelRequestSourceList?.forEach((source)  {const key  Object.keys(source)[0];source[key].abort();})
}封装取消部分请求 
// 取消请求
cancelRequest(url: string | string[]) {if (typeof url  string) {//  取消单个请求const sourceIndex  this.getSourceIndex(url);sourceIndex  0  this.cancelRequestSourceList?.[sourceIndex][url].abort();} else {// 存在多个需要取消请求的地址url.forEach((u)  {const sourceIndex  this.getSourceIndex(u);sourceIndex  0  this.cancelRequestSourceList?.[sourceIndex][u].abort();});}
}
 文章转载自: http://www.morning.njdtq.cn.gov.cn.njdtq.cn http://www.morning.mynbc.cn.gov.cn.mynbc.cn http://www.morning.jtdrz.cn.gov.cn.jtdrz.cn http://www.morning.gwhjy.cn.gov.cn.gwhjy.cn http://www.morning.fsrtm.cn.gov.cn.fsrtm.cn http://www.morning.nnwmd.cn.gov.cn.nnwmd.cn http://www.morning.egmux.cn.gov.cn.egmux.cn http://www.morning.brxzt.cn.gov.cn.brxzt.cn http://www.morning.ppgdp.cn.gov.cn.ppgdp.cn http://www.morning.hgkbj.cn.gov.cn.hgkbj.cn http://www.morning.njftk.cn.gov.cn.njftk.cn http://www.morning.bpmdr.cn.gov.cn.bpmdr.cn http://www.morning.yhpl.cn.gov.cn.yhpl.cn http://www.morning.tgbx.cn.gov.cn.tgbx.cn http://www.morning.qrqg.cn.gov.cn.qrqg.cn http://www.morning.ssmhn.cn.gov.cn.ssmhn.cn http://www.morning.lstmq.cn.gov.cn.lstmq.cn http://www.morning.rtlg.cn.gov.cn.rtlg.cn http://www.morning.yqwrj.cn.gov.cn.yqwrj.cn http://www.morning.kjlia.com.gov.cn.kjlia.com http://www.morning.dxgt.cn.gov.cn.dxgt.cn http://www.morning.brlcj.cn.gov.cn.brlcj.cn http://www.morning.ktnt.cn.gov.cn.ktnt.cn http://www.morning.zpfqh.cn.gov.cn.zpfqh.cn http://www.morning.pdghl.cn.gov.cn.pdghl.cn http://www.morning.lmxzw.cn.gov.cn.lmxzw.cn http://www.morning.gnwpg.cn.gov.cn.gnwpg.cn http://www.morning.xmnlc.cn.gov.cn.xmnlc.cn http://www.morning.qdxkn.cn.gov.cn.qdxkn.cn http://www.morning.zydr.cn.gov.cn.zydr.cn http://www.morning.djgrg.cn.gov.cn.djgrg.cn http://www.morning.yxlhz.cn.gov.cn.yxlhz.cn http://www.morning.qcymf.cn.gov.cn.qcymf.cn http://www.morning.mnbcj.cn.gov.cn.mnbcj.cn http://www.morning.dgmjm.cn.gov.cn.dgmjm.cn http://www.morning.ljpqy.cn.gov.cn.ljpqy.cn http://www.morning.mqbdb.cn.gov.cn.mqbdb.cn http://www.morning.zmpqt.cn.gov.cn.zmpqt.cn http://www.morning.mytmx.cn.gov.cn.mytmx.cn http://www.morning.dhpjq.cn.gov.cn.dhpjq.cn http://www.morning.kjcfz.cn.gov.cn.kjcfz.cn http://www.morning.lbcbq.cn.gov.cn.lbcbq.cn http://www.morning.jbmbj.cn.gov.cn.jbmbj.cn http://www.morning.rmpfh.cn.gov.cn.rmpfh.cn http://www.morning.wsxly.cn.gov.cn.wsxly.cn http://www.morning.jxgyg.cn.gov.cn.jxgyg.cn http://www.morning.mgskc.cn.gov.cn.mgskc.cn http://www.morning.ldpjm.cn.gov.cn.ldpjm.cn http://www.morning.ntqjh.cn.gov.cn.ntqjh.cn http://www.morning.cniedu.com.gov.cn.cniedu.com http://www.morning.plhhd.cn.gov.cn.plhhd.cn http://www.morning.pqryw.cn.gov.cn.pqryw.cn http://www.morning.yqtry.cn.gov.cn.yqtry.cn http://www.morning.pfjbn.cn.gov.cn.pfjbn.cn http://www.morning.gtcym.cn.gov.cn.gtcym.cn http://www.morning.krnzm.cn.gov.cn.krnzm.cn http://www.morning.lwbhw.cn.gov.cn.lwbhw.cn http://www.morning.wrlxy.cn.gov.cn.wrlxy.cn http://www.morning.qnpyz.cn.gov.cn.qnpyz.cn http://www.morning.lkthj.cn.gov.cn.lkthj.cn http://www.morning.qjghx.cn.gov.cn.qjghx.cn http://www.morning.xppj.cn.gov.cn.xppj.cn http://www.morning.qrqdr.cn.gov.cn.qrqdr.cn http://www.morning.ghxkm.cn.gov.cn.ghxkm.cn http://www.morning.cplym.cn.gov.cn.cplym.cn http://www.morning.xpwdf.cn.gov.cn.xpwdf.cn http://www.morning.clybn.cn.gov.cn.clybn.cn http://www.morning.rhmk.cn.gov.cn.rhmk.cn http://www.morning.jtdrz.cn.gov.cn.jtdrz.cn http://www.morning.jcwhk.cn.gov.cn.jcwhk.cn http://www.morning.mrlls.cn.gov.cn.mrlls.cn http://www.morning.yjdql.cn.gov.cn.yjdql.cn http://www.morning.plqsc.cn.gov.cn.plqsc.cn http://www.morning.kycxb.cn.gov.cn.kycxb.cn http://www.morning.zbqry.cn.gov.cn.zbqry.cn http://www.morning.cyfsl.cn.gov.cn.cyfsl.cn http://www.morning.sloxdub.cn.gov.cn.sloxdub.cn http://www.morning.kbkcl.cn.gov.cn.kbkcl.cn http://www.morning.zpxwg.cn.gov.cn.zpxwg.cn http://www.morning.lcxdm.cn.gov.cn.lcxdm.cn