1、问题描述
直接为umi的request方法配置拦截器,当多条请求同时触发时,发现同一个请求会触发拦截器代码多次执行。
import { request } from '@umijs/max';
export const requestOrigin = (url, opts) => {
return request(url, {
// umi中的request对拦截器注入实现有bug, 多个接口同时并发的情况下会导致拦截函数被多次执行
requestInterceptors: [requestInterceptor1, requestInterceptor2, requestInterceptor3],
responseInterceptors: [responseInterceptor1, responseInterceptor2],
...opts,
}).then(() => {
// xxx
}).catch(() => {
// xxx
});
}
2、解决方案
改用 injectInterceptors() 进行拦截器注入。
import { request } from '@umijs/max';
export const requestOrigin = (url, opts) => {
injectInterceptors();
return request(url, {
...opts,
}).then(() => {
// xxx
}).catch(() => {
// xxx
});
}
injectInterceptors实现如下:
import { getRequestInstance } from '@umijs/max';
import isArray from 'lodash-es/isArray';
// 注入标志器,保证全局仅注入一次
let hasInject = false;
// 请求拦截器
const requestInterceptors = [requestInterceptor1, requestInterceptor2, requestInterceptor3];
// 返回拦截器
const responseInterceptors = [responseInterceptor1, responseInterceptor2];
export function injectInterceptors() {
if (!hasInject) {
const requestInstance = getRequestInstance();
requestInterceptors.forEach((interceptor: any) => {
if (isArray(interceptor)) {
requestInstance.interceptors.request.use((config) => {
const { url } = config;
if (interceptor[0].length === 2) {
const { url: newUrl, options } = interceptor[0](url, config);
return { ...options, url: newUrl };
}
return interceptor[0](config);
}, interceptor[1]);
} else {
requestInstance.interceptors.request.use((config) => {
const { url } = config;
if (interceptor.length === 2) {
const { url: newUrl, options } = interceptor(url as string, config) as any;
return { ...options, url: newUrl };
}
return interceptor(config);
});
}
});
responseInterceptors.forEach((interceptor) => {
isArray(interceptor)
? requestInstance.interceptors.response.use(interceptor[0], interceptor[1])
: requestInstance.interceptors.response.use(interceptor);
});
}
hasInject = true;
}
export default injectInterceptors;