You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/mx/module/res/LoadRecovery.ts

79 lines
2.4 KiB

3 weeks ago
/** 资源包加载结果 */
export interface LoadResult {
/** 是否全部条目加载成功 */
ok: boolean;
/** 失败条目键(bundle/path/name) */
failed: string[];
}
/** 加载恢复默认参数 */
export const LoadRecoveryConfig = {
/** 单次 await 默认超时(毫秒) */
defaultTimeoutMs: 30000,
/** loadBundle 超时;须短于 loading 看门狗,失败后才能再点页面 */
bundleTimeoutMs: 20000,
/** 单预制 bundle.load 超时 */
prefabTimeoutMs: 20000,
/** loadDir 超时(首包整目录下载比单预制久) */
dirTimeoutMs: 60000,
/** Tab 预载等待超时 */
tabIntentTimeoutMs: 25000,
/** 战斗 warm 等待超时(与 loadDir 对齐;超时后走进战加载,不得卡匹配页) */
battleWarmTimeoutMs: 60000,
/** loadResPakg 失败重试次数 */
maxRetry: 2,
};
/**
* 为 Promise 增加超时;超时 reject 并带上 label 便于 recover 打点。
*/
export function awaitWithTimeout<T>(
promise: Promise<T>,
timeoutMs: number,
label: string,
): Promise<T> {
if (timeoutMs <= 0) return promise;
return new Promise<T>((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error(`[LoadRecovery] timeout:${label}:${timeoutMs}ms`));
}, timeoutMs);
promise.then(
(v) => {
clearTimeout(timer);
resolve(v);
},
(e) => {
clearTimeout(timer);
reject(e);
},
);
});
}
/**
* 带重试的加载:仅当 result.ok 为 false 或抛错时重试。
*/
export async function loadWithRetry(
loadFn: () => Promise<LoadResult>,
opts?: { maxRetry?: number; label?: string },
): Promise<LoadResult> {
const maxRetry = opts?.maxRetry ?? LoadRecoveryConfig.maxRetry;
const label = opts?.label ?? 'load';
let last: LoadResult = { ok: false, failed: ['unknown'] };
for (let attempt = 0; attempt <= maxRetry; attempt++) {
try {
last = await loadFn();
if (last.ok) return last;
} catch (e) {
console.error(`[LoadRecovery] ${label} attempt ${attempt}`, String(e));
last = { ok: false, failed: [String(e)] };
}
}
return last;
}
/** 拼装失败资源键,供日志与 PF */
export function formatLoadKey(bundle: string, path: string, name: string): string {
return `${bundle}:${path}${name}`;
}