要将这段代码改造为异步模式,可以使用 Promise 或 async/await 结合异步 XHR(或更现代的 fetch
API)。以下是具体改造方案:
方案 1:使用 异步 XHR + Promise
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) {
try {
const conf = JSON.parse(xhr.responseText);
resolve(conf);
} catch (e) {
reject(new Error("Failed to parse config JSON"));
}
} else {
reject(new Error(`Request failed with status ${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) {
// Handle fetch case
} else {
sdpHook(self, conf, "worker");
}
})
.catch(error => console.error("Failed to load config:", error));
方案 2:使用 Fetch API(更简洁)
async function fetchConfigAsync() {
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`;
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error ${response.status}`);
const conf = await response.json();
if ('onclick' in self) {
sdpHook(self, conf, "main");
} else if ('onfetch' in self) {
// Handle fetch case
} else {
sdpHook(self, conf, "worker");
}
} catch (error) {
console.error("Failed to load config:", error);
}
}
// 调用
fetchConfigAsync();
关键改进点
- 非阻塞:异步请求不会冻结线程,其他代码可以继续执行。
- 错误处理:通过
try/catch
(或.catch()
)集中处理网络/解析错误。 - 现代语法:
fetch
API 自动返回 Promise,支持async/await
。path.endsWith("/")
替代手动长度检查。
注意事项
- 兼容性:如果需支持旧浏览器(如 IE),需用回 XHR + Promise。
- 依赖注入:若
sdpHook
是外部依赖,确保它在调用前已加载。
改造后,你的应用将不再因同步请求卡住,整体响应性和用户体验会显著提升!
内容由零声教学AI助手提供,问题来源于学员提问