尽可能的自动化解决js脚本引入失败后重试
重试代码放在head所有js脚本之前
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js加载重试</title>
<script>
const standbyDomains = [
'static.test.com',
'static0.test.com',//error
'static1.test.com',//error
'static2.test.com',
'static3.test.com',//error
'static4.test.com',
];
const retryMaps = {};
window.addEventListener('error', function (e) {
if (e instanceof ErrorEvent || e.target.tagName !== 'SCRIPT') {
return;
}
let url = new URL(e.target.src);
let pathname = url.pathname;
if (!retryMaps[pathname]) {
retryMaps[pathname] = 0;
}
let index = retryMaps[pathname];
if (index >= standbyDomains.length) {
return;
}
const scriptElement = e.target;
const isDefer = scriptElement.hasAttribute('defer');
const isAsync = scriptElement.hasAttribute('async');
url.hostname = standbyDomains[index];
let newUrl = url.toString();
let scriptStr = `<script src='${newUrl}'`;
if (isDefer) {
scriptStr += ` defer>\<\/script>`;
} else if (isAsync) {
scriptStr += ` async>\<\/script>`;
} else {
scriptStr += `>`;
}
scriptStr += `\<\/script>`;
document.write(scriptStr);
retryMaps[pathname]++;
}, true);
</script>
</head>
<body>
<script src="http://static0.test.com/1.js"></script>
<script src="http://static.test.com/2.js"></script>
<script src="http://static.test.com/3.js"></script>
</body>
</html>
知识点
standbyDomains
:定义了备用域名列表。retryMaps
:用于记录每个路径的错误次数。window.addEventListener('error',...)
:监听全局的错误事件,第三个参数设置为 true
(表示事件捕获阶段触发),这样能确保更早地捕获到错误。
defer
或 async
属性构建合适的新脚本字符串,通过 document.write
输出。关于错误冒泡:
在 JavaScript 中,错误通常会从具体发生错误的元素向上冒泡,直到被捕获或到达全局。通过设置事件监听的第三个参数为 true
进行捕获阶段监听,可以在错误冒泡到全局之前就截获到它,及时进行处理,避免错误进一步传播和可能导致的不良影响。这种方式可以更全面、更早地处理脚本错误等情况,增强程序的健壮性和稳定性。
总结:这段代码主要利用事件监听在捕获阶段处理脚本加载错误,自动切换备用域名重新加载,并根据属性设置新脚本,同时利用错误冒泡的特性,在错误传播早期进行干预和处理。