【JavaScript】实现axios的拦截器
2023/02/10 10:31:50
axios 拦截器的配置方式
详细配置方式见这里:拦截器的配置方式。
简单来说就是:用 use()
方法注册拦截器,在调用 request()
方法时调用拦截器。
axios.interceptors.request.use(
(config) => {},
(error) => {}
);
axios.interceptors.request.use(
(config) => {},
(error) => {}
);
axios.interceptors.response.use(
(response) => {},
(error) => {}
);
axios.get("https://www.xxx.com").then(
(response) => {},
(error) => {}
);
use()
方法的一参为处理逻辑,处理逻辑如果报错则执行二参的错误处理逻辑。
这里只考虑同步的执行方式,需要实现的功能包括:
- 请求拦截器。
- 请求拦截器的一参函数接收 config 对象,返回新的 config 对象,最终的
request()
方法用的是最后一个拦截器返回的 config 对象。 use()
一参函数报错就执行二参函数,接收 error 对象作为参数。- 设置多个请求拦截器时后设置的先执行。
- 请求拦截器的一参函数接收 config 对象,返回新的 config 对象,最终的
- 响应拦截器。
- 响应拦截器的一参函数接收响应对象,返回新的响应对象,最终的
request()
方法返回最后一个响应拦截器返回的响应对象。 - 响应拦截器总是在请求响应之后按照设置顺序执行。
- 响应拦截器的一参函数接收响应对象,返回新的响应对象,最终的
模拟发送请求
先模拟实现一个简易的 axios:
function dispatchRequest(config) {
if (config.error) {
return Promise.reject(config.error);
}
const response = {
result: true,
data: config,
};
return Promise.resolve(response);
}
class Axios {
request(url) {
const config = {
url,
};
return dispatchRequest(config);
}
}
const axios = new Axios();
dispatchRequest()
方法为模拟发送请求方法,接收 config,返回响应对象,为方便观察,响应对象的 data 为传入的 config。
如果 config.error 为 true 表示请求失败,request()
返回 error 对象,否则表示请求成功,返回响应对象。
axios
.request("https://www.xxx.com", {})
.then((res) => {
console.log("success", res);
})
.catch((error) => {
console.log("error", error);
});
注册拦截器
拦截器是通过 use()
方法注册的,这里模拟实现 use()
方法。
function use(onFulfilled, onRejected) {
this.handlers.push(onFulfilled, onRejected);
}
class Axios {
interceptors = {
request: {
handlers: [],
},
response: {
handlers: [],
},
};
constructor() {
this.interceptors.request.use = this.interceptors.response.use = use;
}
}
将传入 use()
的方法都 push 到 handlers 数组中。
触发拦截器
拦截器在 request()
方法中触发。
class Axios {
interceptors = {
request: {
handlers: [],
},
response: {
handlers: [],
},
};
constructor() {
this.interceptors.request.use = this.interceptors.response.use = use;
}
request(url, config) {
const fullConfig = Object.assign(
{
url,
},
config
);
const chain = [dispatchRequest, null];
// 请求拦截器
const requestInterceptor = this.interceptors.request.handlers;
let index = 0;
let len = requestInterceptor.length;
while (index < len) {
chain.unshift(requestInterceptor[index++], requestInterceptor[index++]);
}
// 响应拦截器
const responseInterceptor = this.interceptors.response.handlers;
index = 0;
len = responseInterceptor.length;
while (index < len) {
chain.push(responseInterceptor[index++], responseInterceptor[index++]);
}
// 合并为 Promise 链
let promise = Promise.resolve(fullConfig);
index = 0;
len = chain.length;
while (index < len) {
promise = promise.then(chain[index++], chain[index++]);
}
return promise;
}
}
完整代码
function dispatchRequest(config) {
if (config.error) {
return Promise.reject(config.error);
}
const response = {
result: true,
data: config,
};
return Promise.resolve(response);
}
function use(onFulfilled, onRejected) {
this.handlers.push(onFulfilled, onRejected);
}
class Axios {
interceptors = {
request: {
handlers: [],
},
response: {
handlers: [],
},
};
constructor() {
this.interceptors.request.use = this.interceptors.response.use = use;
}
request(url, config) {
const fullConfig = Object.assign(
{
url,
},
config
);
const chain = [dispatchRequest, null];
// 请求拦截器
const requestInterceptor = this.interceptors.request.handlers;
let index = 0;
let len = requestInterceptor.length;
while (index < len) {
chain.unshift(requestInterceptor[index++], requestInterceptor[index++]);
}
// 响应拦截器
const responseInterceptor = this.interceptors.response.handlers;
index = 0;
len = responseInterceptor.length;
while (index < len) {
chain.push(responseInterceptor[index++], responseInterceptor[index++]);
}
// 合并为 Promise 链
let promise = Promise.resolve(fullConfig);
index = 0;
len = chain.length;
while (index < len) {
promise = promise.then(chain[index++], chain[index++]);
}
return promise;
}
}
const axios = new Axios();