From ee93c1c5fc1d3e1e6a8cab9ffc1f72cd1700cdaa Mon Sep 17 00:00:00 2001 From: AnthonyDuan Date: Sun, 23 Nov 2025 12:56:28 +0800 Subject: [PATCH] fix(loader): add 15s timeout and CSS load events to prevent 97% hang; show diagnostics on failure --- public/src/js/loader.js | 21 ++++++++++++--------- public/src/js/pageevents.js | 8 +++++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/public/src/js/loader.js b/public/src/js/loader.js index f12b33d..ce23f64 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -55,21 +55,23 @@ class Loader{ ){ reject("Version on the page and config does not match\n(page: " + pageVersion + ",\nconfig: "+ gameConfig._version.commit + ")") } - var cssCount = document.styleSheets.length + assets.css.length + var loaded = 0 + var total = assets.css.length assets.css.forEach(name => { var stylesheet = document.createElement("link") stylesheet.rel = "stylesheet" stylesheet.href = "src/css/" + name + this.queryString + stylesheet.addEventListener("load", () => { + loaded++ + if(loaded >= total){ + resolve() + } + }) + stylesheet.addEventListener("error", () => { + reject("src/css/" + name) + }) document.head.appendChild(stylesheet) }) - var checkStyles = () => { - if(document.styleSheets.length >= cssCount){ - resolve() - clearInterval(interval) - } - } - var interval = setInterval(checkStyles, 100) - checkStyles() })) for(var name in assets.fonts){ @@ -540,6 +542,7 @@ class Loader{ ajax(url, customRequest, customResponse){ var request = new XMLHttpRequest() request.open("GET", url) + request.timeout = 15000 var promise = pageEvents.load(request) if(!customResponse){ promise = promise.then(() => { diff --git a/public/src/js/pageevents.js b/public/src/js/pageevents.js index de94814..ab61938 100644 --- a/public/src/js/pageevents.js +++ b/public/src/js/pageevents.js @@ -76,7 +76,11 @@ class PageEvents{ } load(target){ return new Promise((resolve, reject) => { - this.race(target, "load", "error", "abort").then(response => { + var timer = setTimeout(() => { + reject(["Loading timeout", target]) + }, 15000) + this.race(target, "load", "error", "abort", "timeout").then(response => { + clearTimeout(timer) switch(response.type){ case "load": return resolve(response.event) @@ -84,6 +88,8 @@ class PageEvents{ return reject(["Loading error", target]) case "abort": return reject("Loading aborted") + case "timeout": + return reject(["Loading timeout", target]) } }) })