- 首页 > 睿知 > it技术 > >
//拦截器
class InterceptorsManage{
constructor(){
this.handlers=[];
}use(resolve,reject){
this.handlers.push({
resolve,
reject
})
}
}//取消请求
class CancelToken{
constructor(exactor){
//将promise给cancel。防止多次重复cancel
let resolvePromise;
//promise实例的resolve方法
this.promise=new Promise(resolve=>{
resolvePromise=resolve;
})
this.reason=undefined;
const cancel=message=>{
if(this.reason){return}
this.reason='cancel'+message;
resolvePromise(this.reason);
//改变this.promise为resolve状态
}
exactor(cancel)
}
throwIfRequested() {
if(this.reason) {
throw this.reason
}
}
source(){
let cancel;
//等于上面的cancel,一个函数
const token=new CancelToken(function exactor(c){
cancel=c;
});
return {
token,
cancel
}
}
}class Axios{
constructor(){
this.interceptors={
request:new InterceptorsManage,
response:new InterceptorsManage
}
}request(config){
//拦截器和请求组装队列
let chain=[this.sendAjax.bind(this),undefined];
//成对出现,一个成功一个失败,失败回调暂不处理
//请求拦截,调用request请求时,请求拦截在前,响应拦截在后
this.interceptors.request.handlers.forEach(inter=>{
chain.unshift(inter.resolve,inter.reject)
})
this.interceptors.response.handlers.forEach(inter=>{
chain.push(inter.resolve,inter.reject)
})//执行队列,每次执行一对,并给promise最新的值
let promise=Promise.resolve(config);
while(chain.length>0){
//promise状态是resolved会执行then中第一个回调,1.request.use(成功,失败),2.成功把resolve(config)成功结果给到sendAjax参数执行,3.sendAjax执行成功,把结果response给response.use(成功)参数执行
promise=promise.then(chain.shift(),chain.shift())
}
return promise;
}
sendAjax(config){
return new Promise(resolve=>{
const {url='',method='get',data=https://www.it610.com/article/{}}=config;
//发送请求
const xhr=new XMLHttpRequest();
xhr.open(method,url,true);
xhr.onreadystatechange=()=>{
if (xhr.status >= 200 && xhr.status <= 300 && xhr.readyState === 4) {
resolve(xhr.responseText)
} else {
reject('失败了')
}
};
if(config.cancelToken){
//promise为resolve状态时,取消请求
config.cancelToken.promise.then(function onCancel(reason){//onCancel就是上面的resolvePromise
if(!xhr){return}
xhr.abort();
//取消请求
reject(reason)
xhr=null;
})
}
xhr.send(data)
})
}
};
//定义get,post等方法,挂到Axios上
const methodsArr=['get','delete','head','options','put','patch','post'];
methodsArr.forEach(met=>{
Axios.prototype[met]=function(){
console.log('执行'+met+'方法');
//处理单个方法,带2个参数(url,config)
if(['get','delete','head','options'].includes(met)){
return this.request({
method:met,
url:arguments[0],
...arguments[1]||{}
})
}else{//3个参数(url,data,config),put,post有data
return this.request({
method:met,
url:arguments[0],
data:arguments[1]||{},
...arguments[2]||{}
})
}
}
});
//继承类的方法及属性
function extend(to,from,ctx){
for(let key in from){
//继承自身属性,不继承原型链,用hasOwnProperty判断
if(from.hasOwnProperty(key)){
if(typeof from[key]==='function'){
to[key]=from[key].bind(ctx)
}else{
to[key]=from[key]
}
}
}
return to;
};
//引用
function createInstance(){
let context=new Axios();
//用实例化的context对象去接替Axios类的的request方法,支持axios({...})方法
let instance=Axios.prototype.request.bind(context);
//继承get,post,put等方法
extend(instance,Axios.prototype,context);
extend(instance,context)
return instance;
}
let axios=createInstance();
//加拦截器
axios.interceptors.request.use(function(config){
//发送之前做什么
return config;
},function(err){
//请求出错
return Promise.reject(error)
});
axios.interceptors.response.use(function(response){
//响应数据做什么
return response;
},function(err){
return Promise.reject(err)
})//取消请求
// const {token,cancel}=cancelToken.source();
// config.cancelToken=token;
// setTimeout(()=>cancel,500)
推荐阅读