前景提要:
ts 簡(jiǎn)易封裝 axios,統(tǒng)一 API
實(shí)現(xiàn)在 config 中配置開(kāi)關(guān)攔截器
axios 實(shí)現(xiàn)請(qǐng)求 loading 效果文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-741945.html
用一個(gè)數(shù)組保存當(dāng)前請(qǐng)求的 url,此時(shí)還未響應(yīng)。如果再次發(fā)起同樣請(qǐng)求,比對(duì) url 發(fā)現(xiàn)已經(jīng)存在數(shù)組中,則攔截請(qǐng)求,提示重復(fù)提交。當(dāng)該請(qǐng)求響應(yīng)結(jié)束后,就將 url 從數(shù)組中剔除。則可再次發(fā)起上一次 url 的請(qǐng)求。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-741945.html
封裝攔截器
import { AxiosError } from "axios";
import { ElMessage } from "element-plus";
import { MyAxiosResponse, MyInternalAxiosRequestConfig } from "./request";
let pendingUrl: string[] = []; // pending 狀態(tài)的請(qǐng)求 url
const excludeUrl: string[] = ["/upload", "/upload/chunk"]; // 排除不需要攔截的url。比如并發(fā)上傳文件的 url 都是一樣的,就需要排除
/**
* 比較請(qǐng)求的 url
* @param {import("..").AxiosRequestConfig} config
* @returns
*/
export function compareUrl(config: MyInternalAxiosRequestConfig) {
// 配置中明確標(biāo)出 debounce 為 false,則關(guān)閉請(qǐng)求防抖。不寫(xiě)或者為 true,則開(kāi)啟防抖
if (config.debounce === false) return config;
// 白名單 url 不防抖處理
if (config.url && excludeUrl.includes(config.url)) return config;
if (config.url && pendingUrl.includes(config.url)) {
// alert("重復(fù)請(qǐng)求");
ElMessage.warning("請(qǐng)求頻繁");
throw new Error("請(qǐng)求頻繁");
} else {
config.url && pendingUrl.push(config.url);
}
return config;
}
/**
* 請(qǐng)求成功,過(guò)濾請(qǐng)求完畢的 url
* @param {import("axios").AxiosResponse} res
* @returns
*/
export function filterFulfilledUrlOnFulfilled(res: MyAxiosResponse) {
pendingUrl = pendingUrl.filter(item => item != res.config.url);
return res;
}
/**
* 請(qǐng)求錯(cuò)誤,過(guò)濾請(qǐng)求完畢的 url
* @param {import("axios").AxiosError} err
* @returns
*/
export function filterFulfilledUrlOnRejected(err: AxiosError) {
pendingUrl = pendingUrl.filter(item => item != err?.config?.url);
throw err;
}
補(bǔ)充 config 配置并注冊(cè)攔截器
const DEFAULT_EXTRA_FEATURE_CONFIG = { showLoading: true, showMessage: true, debounce: true, retry: true };
/** 擴(kuò)展 axios 的請(qǐng)求配置類(lèi)型 */
export interface MyAxiosRequestConfig<TReqBodyData = any> extends AxiosRequestConfig<TReqBodyData> {
interceptors?: {
reqInterceptorOnFulfilled?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
reqInterceptorOnRejected?: (err: AxiosError) => any;
resInterceptorOnFulfilled?: (res: AxiosResponse) => AxiosResponse;
resInterceptorOnRejected?: (err: AxiosError) => Promise<AxiosError>;
};
showLoading?: boolean;
showMessage?: boolean;
debounce?: boolean;
retry?: boolean;
}
/** 給攔截器使用 */
export interface MyInternalAxiosRequestConfig extends InternalAxiosRequestConfig {
showLoading?: boolean;
showMessage?: boolean;
debounce?: boolean;
retry?: boolean;
}
import HttpRequest from "./http/request";
import { compareUrl, filterFulfilledUrlOnFulfilled, filterFulfilledUrlOnRejected } from "./http/debounceReq";
import { closeLoadingOnFulfilled, closeLoadingOnRejected, showLoading } from "./http/loading";
import { responseMessageOnFulfilled } from "./http/message";
import { getTokenResponseInterceptor, setAccessTokenRequestInterceptor } from "./http/token";
import { retryRequest } from "./http/retryRequest";
const httpRequest = new HttpRequest({
baseURL: import.meta.env.VITE_APP_API_BASE_URL,
timeout: import.meta.env.VITE_APP_API_TIMEOUT
});
// loading
httpRequest.getInstance().interceptors.request.use(showLoading);
httpRequest.getInstance().interceptors.response.use(closeLoadingOnFulfilled, closeLoadingOnRejected);
// debounceRequest
httpRequest.getInstance().interceptors.request.use(compareUrl);
httpRequest.getInstance().interceptors.response.use(filterFulfilledUrlOnFulfilled, filterFulfilledUrlOnRejected);
export default httpRequest;
``
到了這里,關(guān)于防止重復(fù)提交請(qǐng)求的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!