120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import axios, {type AxiosInstance, type AxiosResponse, type InternalAxiosRequestConfig} from "axios";
|
|
import {ApiResponse} from "../types";
|
|
|
|
export type ErrorCallback = (response: ApiResponse<any>) => void;
|
|
export type RequestInterceptor = (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
|
|
export interface ResponseObserverPayload {
|
|
config?: InternalAxiosRequestConfig;
|
|
status?: number;
|
|
response?: AxiosResponse;
|
|
error?: any;
|
|
serverResponse?: ApiResponse<any>;
|
|
}
|
|
export type ResponseObserver = (payload: ResponseObserverPayload) => void;
|
|
|
|
let globalErrorCallback: ErrorCallback | null = null;
|
|
let globalRequestInterceptor: RequestInterceptor | null = null;
|
|
let globalResponseObserver: ResponseObserver | null = null;
|
|
|
|
export const setGlobalErrorCallback = (callback: ErrorCallback) => {
|
|
globalErrorCallback = callback;
|
|
};
|
|
|
|
export const setGlobalRequestInterceptor = (callback: RequestInterceptor | null) => {
|
|
globalRequestInterceptor = callback;
|
|
};
|
|
|
|
export const setGlobalResponseObserver = (callback: ResponseObserver | null) => {
|
|
globalResponseObserver = callback;
|
|
};
|
|
|
|
const notifyResponseObserver = (payload: ResponseObserverPayload) => {
|
|
if (!globalResponseObserver) {
|
|
return;
|
|
}
|
|
globalResponseObserver(payload);
|
|
};
|
|
|
|
const applyDefaultInterceptors = (instance: AxiosInstance) => {
|
|
instance.defaults.withCredentials = true;
|
|
instance.interceptors.request.use((config) => {
|
|
if (globalRequestInterceptor) {
|
|
return globalRequestInterceptor(config);
|
|
}
|
|
return config;
|
|
});
|
|
instance.interceptors.response.use((axiosResp: any) => {
|
|
if (!axiosResp.config.responseType) {
|
|
// 服务端返回
|
|
const serverResp = axiosResp.data as ApiResponse<any>;
|
|
if (serverResp.code < 40000) {
|
|
notifyResponseObserver({
|
|
config: axiosResp?.config,
|
|
status: axiosResp?.status,
|
|
response: axiosResp,
|
|
serverResponse: serverResp
|
|
});
|
|
// 200 或 300 HTTP 状态段视为成功
|
|
return serverResp.data;
|
|
} else {
|
|
notifyResponseObserver({
|
|
config: axiosResp?.config,
|
|
status: axiosResp?.status,
|
|
response: axiosResp,
|
|
serverResponse: serverResp,
|
|
error: serverResp.message
|
|
});
|
|
if (globalErrorCallback) {
|
|
globalErrorCallback(serverResp);
|
|
}
|
|
// 由调用方处理
|
|
return Promise.reject(serverResp.message);
|
|
}
|
|
}
|
|
notifyResponseObserver({
|
|
config: axiosResp?.config,
|
|
status: axiosResp?.status,
|
|
response: axiosResp
|
|
});
|
|
return axiosResp.data;
|
|
}, (error: any) => {
|
|
notifyResponseObserver({
|
|
config: error?.config,
|
|
status: error?.response?.status,
|
|
response: error?.response,
|
|
error
|
|
});
|
|
// 请求错误
|
|
if (error) {
|
|
if (error.response && error.response.status) {
|
|
throw error;
|
|
}
|
|
if (error.request) {
|
|
if (error.message && error.message.startsWith("timeout")) {
|
|
throw new Error("time out");
|
|
} else {
|
|
throw new Error(error.message || "request error");
|
|
}
|
|
}
|
|
}
|
|
throw error;
|
|
});
|
|
};
|
|
|
|
const axiosInstance = axios.create();
|
|
applyDefaultInterceptors(axiosInstance);
|
|
|
|
export const createServiceAxios = (baseURL?: string) => {
|
|
const instance = axios.create({ baseURL });
|
|
applyDefaultInterceptors(instance);
|
|
return instance;
|
|
};
|
|
|
|
export default {
|
|
axios: axiosInstance,
|
|
setGlobalErrorCallback,
|
|
setGlobalRequestInterceptor,
|
|
setGlobalResponseObserver,
|
|
createServiceAxios
|
|
};
|