Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 今天这里主要是拦截器这里做一些分析,并且自动动手实现一个简化版本的便于理解。
1、拦截器分为请求拦截器,和响应body拦截器
2、请求拦截器的主要作用,可以理解为给请求body加一下附带参数,如请求token,或者对请求做一些过滤,比如判定请求时一个非法请求时直接reject。
3、响应body拦截器的作用在于可以在框架级别对于响应body的内容进行合适的处理,比如401的http status code直接导航用到到登录页进行重新鉴权,亦或者直接做一个续期token的操作,并且在续期成功之后直接重放刚才的请求。
4、所以,感觉拦截器是axios的精华部分。
/**
* 一个及其简单的axios版本
*/
class Firs {
interceptors = {
request: new InterceptorManger(),
response: new InterceptorManger(),
}
constructor({ baseUrl, timeout, headers }) {
this.baseUrl = baseUrl;
this.timeout = timeout;
this.headers = headers;
}
//请求真正发送在此处,axios的这里实现是根据node和浏览器的版本分别做了两个adapter
dispatchRequest() {
return new Promise((resolve, reject) => {
try {
console.log('dispatchRequest method execute...');
setTimeout(() => {
resolve('dispatchRequest response here!');
// reject('1');
}, 3000);
} catch (e) {
reject(e);
}
});
}
request() {
let promise = Promise.resolve(this);
let chain = [this.dispatchRequest, undefined];
const requestInterceptorChain = [];
while (this.interceptors.request.handlers.length > 0) {
requestInterceptorChain.unshift(
this.interceptors.request.handlers.shift(),
this.interceptors.request.handlers.shift(),
);
}
Array.prototype.unshift.apply(chain, requestInterceptorChain);
chain = chain.concat(this.interceptors.response.handlers);
while (chain.length > 0) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
}
class InterceptorManger {
handlers = []
use(fulfilled, rejected) {
this.handlers.push(
fulfilled,
rejected,
);
}
}
// 下面是验证逻辑
const fire = new Firs({
baseUrl: 'https://baseurl.com/',
timeout: 4000,
headers: {
xDev: 'xDev',
},
});
//添加两个请求拦截器
fire.interceptors.request.use((config) => {
// eslint-disable-next-line no-param-reassign
config.headers.interceptors = '1111';// 修改一个header试试
console.log(`request interceptor 1 execute..${JSON.stringify(config)}`);
// return config;
return Promise.reject('用户需要登录');
}, (err) => {
console.log(`request interceptor 1 ${err}`);
return Promise.reject(err);
});
fire.interceptors.request.use((config) => {
console.log(`request interceptor 2 execute..${JSON.stringify(config)}`);
return config;
}, (err) => {
console.log(`request interceptor 2 ${err}`);
return Promise.reject(err);
});
//添加一个响应拦截器
fire.interceptors.response.use((response) => {
console.log(`response interceptor 1 execute..${response}`);
return response;
}, (err) => {
console.log(`response interceptor 1 ${err}`);
return Promise.reject(err);
});
fire.request().then((res) => {
console.log('请求正常');
console.log(res);
})
.catch((err) => {
console.log('请求发送错误');
console.log(err);
});
其主要的原理在于 给 真正的请求 dispatchRequest 的前面增加 请求拦截器的执行,后面增加响应拦截器的执行,注意,这里按照axios的原理还原,所以,请求拦截器的执行顺序按照后添加先执行的方式来做。
shift操作把数据最前面的元素拿出来,然后在unshift到一个数字,所以顺序就调转过来了。
最重要的是利用了 promise.then(onFulfilled[, onRejected])
promise.then(onFulfilled[, onRejected]);
promise.then(value => {
// fulfillment
}, reason => {
// rejection
});
这里的实现
while (chain.length > 0) {
promise = promise.then(chain.shift(), chain.shift());
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。