整理代码
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
/**
|
||||
* 看板静态配置。
|
||||
* 这里只存放接口相对路径、外部链接和枚举映射,认证令牌必须由开发代理或生产网关注入。
|
||||
* 这里只存放接口相对路径、固定令牌、外部链接和枚举映射,业务模块统一从这里读取运行配置。
|
||||
*/
|
||||
export const API_BASE = "/qhse_webapi/api/DataGovernance";
|
||||
|
||||
/** 数据治理接口固定令牌,由统一请求服务写入请求头。 */
|
||||
export const API_TOKEN = "AF17168B-87BD-4GLY-1111-F0A0A1158F9B";
|
||||
|
||||
export const API_ENDPOINTS = {
|
||||
monitoring: `${API_BASE}/GetMetricMonitoringSituation`,
|
||||
unitMonitoring: `${API_BASE}/GetUnitMetricMonitoringSituation`,
|
||||
|
||||
+33
-10
@@ -3,12 +3,13 @@
|
||||
* 负责查询参数编码、请求 ID、超时/取消和业务错误归一化,不承载具体业务字段转换。
|
||||
*/
|
||||
import type { ApiEnvelope } from "../types/dashboard";
|
||||
import { API_TOKEN } from "../config/dashboard";
|
||||
|
||||
export class ApiError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public readonly status = 0,
|
||||
public readonly requestId = ""
|
||||
public readonly requestId = "",
|
||||
) {
|
||||
super(message);
|
||||
this.name = "ApiError";
|
||||
@@ -18,7 +19,7 @@ export class ApiError extends Error {
|
||||
export async function getJson<T>(
|
||||
url: string,
|
||||
params: Record<string, string | number | undefined>,
|
||||
options: { timeout?: number; signal?: AbortSignal } = {}
|
||||
options: { timeout?: number; signal?: AbortSignal } = {},
|
||||
): Promise<ApiEnvelope<T>> {
|
||||
const requestId = crypto.randomUUID();
|
||||
const target = new URL(url, window.location.origin);
|
||||
@@ -29,24 +30,46 @@ export async function getJson<T>(
|
||||
|
||||
// 外部 signal 与内部超时共用一个控制器,调用方取消和超时都走相同错误出口。
|
||||
const timeoutController = new AbortController();
|
||||
const timeoutId = window.setTimeout(() => timeoutController.abort(), options.timeout ?? 12000);
|
||||
const timeoutId = window.setTimeout(
|
||||
() => timeoutController.abort(),
|
||||
options.timeout ?? 12000,
|
||||
);
|
||||
const abort = () => timeoutController.abort();
|
||||
options.signal?.addEventListener("abort", abort, { once: true });
|
||||
|
||||
try {
|
||||
const response = await fetch(target, {
|
||||
headers: { Accept: "application/json", "X-Request-Id": requestId },
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
token: API_TOKEN,
|
||||
"X-Request-Id": requestId,
|
||||
},
|
||||
cache: "no-store",
|
||||
signal: timeoutController.signal
|
||||
signal: timeoutController.signal,
|
||||
});
|
||||
if (!response.ok) throw new ApiError(`接口请求失败:HTTP ${response.status}`, response.status, requestId);
|
||||
const result = await response.json() as ApiEnvelope<T>;
|
||||
if (Number(result.code) !== 1) throw new ApiError(result.message || "接口返回业务错误", response.status, requestId);
|
||||
if (!response.ok)
|
||||
throw new ApiError(
|
||||
`接口请求失败:HTTP ${response.status}`,
|
||||
response.status,
|
||||
requestId,
|
||||
);
|
||||
const result = (await response.json()) as ApiEnvelope<T>;
|
||||
if (Number(result.code) !== 1)
|
||||
throw new ApiError(
|
||||
result.message || "接口返回业务错误",
|
||||
response.status,
|
||||
requestId,
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof ApiError) throw error;
|
||||
if (timeoutController.signal.aborted) throw new ApiError("接口请求超时或已取消", 0, requestId);
|
||||
throw new ApiError(error instanceof Error ? error.message : "接口请求失败", 0, requestId);
|
||||
if (timeoutController.signal.aborted)
|
||||
throw new ApiError("接口请求超时或已取消", 0, requestId);
|
||||
throw new ApiError(
|
||||
error instanceof Error ? error.message : "接口请求失败",
|
||||
0,
|
||||
requestId,
|
||||
);
|
||||
} finally {
|
||||
window.clearTimeout(timeoutId);
|
||||
options.signal?.removeEventListener("abort", abort);
|
||||
|
||||
Reference in New Issue
Block a user