Files
timi-web/src/utils/Network.ts
T
2026-08-01 17:35:48 +08:00

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
};