如果 xhr.open
卡住(阻塞主线程),通常是因为您使用了 同步 XHR(xhr.open
的第三个参数为 false
)。现代浏览器已弃用同步 XHR,因为它会导致页面冻结,影响用户体验。以下是解决方案:
✅ 推荐方案:改用异步 XHR + Promise/Callback
function fetchConfigAsync() {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
let path = window.location.pathname;
if (path.endsWith("/")) path = path.slice(0, -1);
const url = sdp_web_appid
? `${path}/sdpwebproxyconf?GratuitousProxy=${sdp_web_appid}`
: `${path}/sdpwebproxyconf`;
xhr.open('GET', url, true); // true = 异步(默认值)
xhr.onload = () => {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`HTTP ${xhr.status}`));
}
};
xhr.onerror = () => reject(new Error("Network error"));
xhr.send();
});
}
// 使用示例(不阻塞后续代码)
fetchConfigAsync()
.then(conf => {
if ('onclick' in self) sdpHook(self, conf, "main");
else if ('onfetch' in self) { /* ... */ }
else sdpHook(self, conf, "worker");
// 【关键】所有依赖配置的代码写在这里
initOtherFunctions();
})
.catch(error => console.error("加载配置失败:", error));
// 【非依赖】的其他代码可立即执行
console.log("正在加载配置,请稍候...");
⚠️ 为什么避免同步 XHR?
- 浏览器警告:Chrome/Firefox 会输出类似
[Deprecation] Synchronous XMLHttpRequest is deprecated
的警告。 - 性能问题:阻塞主线程导致页面无响应(按钮点击、动画等均无法执行)。
- 潜在崩溃:长时间同步请求可能触发浏览器终止脚本。
🌟 终极建议:升级到 Fetch API + Async/Await
更现代的写法(推荐):
async function loadConfig() {
let path = window.location.pathname.replace(/\/$/, "");
const url = sdp_web_appid
? `${path}/sdpwebproxyconf?GratuitousProxy=${sdp_web_appid}`
: `${path}/sdpwebproxyconf`;
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json();
}
// 使用示例
(async () => {
try {
const conf = await loadConfig();
// ...处理配置后的逻辑
} catch (error) { /* ... */ }
})();
❓ 如果必须强制同步?
极少数场景(如旧版浏览器兼容)可尝试:
// ⚠️ 仅作演示,实际不推荐!
const conf = (function() {
let result;
$.ajax({
url: "...",
async: false, // jQuery遗留的同步选项(底层仍是XHR)
success: data => result = data
});
return result;
})();
但强烈建议重构为异步逻辑。
内容由零声教学AI助手提供,问题来源于学员提问