/** * Http管理器 * */ import { sys } from "cc"; import SubManager from 'db://assets/Scripts/Sub/SubManager'; // 请求类型 export type HttpMethod = "GET" | "POST" | "PUT"; // 请求参数结构 export interface HttpSendOptions { headers?: Record; responseType?: XMLHttpRequestResponseType; rawBody?: Document | XMLHttpRequestBodyInit | null; } // 响应结构 export interface HttpRawResponse { ok: boolean; // 是否 2xx status: number; // HTTP 状态码,网络错误/超时为 0 body?: any; // xhr.response 或 xhr.responseText error?: "timeout" | "network" | "http"; } export class HttpManager { private static _I: HttpManager | null = null; public static get I(): HttpManager { if (!HttpManager._I) HttpManager._I = new HttpManager(); return HttpManager._I; } private constructor() {} /** 发起请求,供 ApiClient 使用 */ public async request( url: string, data: any, method: HttpMethod = "GET", opt: HttpSendOptions = {} ): Promise { const xhr = new XMLHttpRequest(); // 超时 xhr.timeout = 10000; // 响应类型 if (opt.responseType) xhr.responseType = opt.responseType; if (method === "GET") { url = url + this.buildQuery(data); xhr.open(method, url, true); if (sys.isNative) { xhr.setRequestHeader("Accept-Encoding", "gzip,deflate"); xhr.setRequestHeader("content-type", "text/html;charset=utf-8"); } } else { xhr.open(method, url, true); if (!opt.rawBody) { xhr.setRequestHeader("Content-Type", "application/json"); } } if (opt.headers) { Object.keys(opt.headers).forEach(k => xhr.setRequestHeader(k, opt.headers![k])); } return new Promise((resolve) => { xhr.onreadystatechange = () => { if (xhr.readyState === 4) { const ok = xhr.status >= 200 && xhr.status < 300; const body = xhr.response ?? xhr.responseText ?? null; if (!ok) { SubManager.ShowPrompt(`网络错误(${xhr.status}),请稍后再试`); } resolve({ ok, status: xhr.status, body, error: ok ? undefined : "http" }); } }; xhr.onerror = () => { SubManager.ShowPrompt("网络错误,请检查网络连接"); resolve({ ok: false, status: 0, error: "network" }); }; xhr.ontimeout = () => { SubManager.ShowPrompt("请求超时,请检查网络连接"); resolve({ ok: false, status: 0, error: "timeout" }); }; if (method === "GET") { xhr.send(); } else { if (opt.rawBody !== undefined) xhr.send(opt.rawBody ?? null); else xhr.send(JSON.stringify(data ?? {})); } }); } /** * 把对象转 ?a=1&b=2 的查询串 */ private buildQuery(json: any) { if (!json || typeof json !== "object") return ""; const pairs = Object.keys(json).map( k => encodeURIComponent(k) + "=" + encodeURIComponent(json[k]) ); return pairs.length ? "?" + pairs.join("&") : ""; } }