网络层
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Http管理器
|
||||
*
|
||||
*/
|
||||
|
||||
import { sys } from "cc";
|
||||
import SubManager from 'db://assets/Scripts/Sub/SubManager';
|
||||
|
||||
// 请求类型
|
||||
export type HttpMethod = "GET" | "POST" | "PUT";
|
||||
// 请求参数结构
|
||||
export interface HttpSendOptions {
|
||||
headers?: Record<string, string>;
|
||||
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<HttpRawResponse> {
|
||||
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<HttpRawResponse>((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("&") : "";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user