JS 脚本加载失败如何重试
2024-07-24 本文已影响0人
Cherry丶小丸子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
const backupDomains = ["123.cn", "456.com", "789.net"];
const nextDomain = {};
window.addEventListener("error", e => {
console.log(e);
if(e instanceof ErrorEvent || e.target.tagName !== "SCRIPT") {
return;
}
const url = new URL(e.target.src);
const pathname = url.pathname;
if(!nextDomain[pathname]) {
nextDomain[pathname] = 0;
}
const index = nextDomain[pathname];
if(index >= backupDomains.length) {
return;
}
const domain = backupDomains[index];
url.hostname = domain;
const newUrl = url.toString();
document.write(`\<script src="${newUrl}">\<\/script>`);
nextDomain[pathname]++;
}, true);
</script>
</head>
一、script标签特性
① script 标签默认是同步加载的。当 HTML 页面在加载的过程中,遇到了一个 script 标签,就会中断 HTML 页面的加载,然后根据对应的 src 地址向服务器发起请求,当对应的 javascript 脚本加载完成后,HTML 页面仍然不能加载,还必须等加载的 javascript 脚本执行完成后,HTML 页面才能继续往下加载。
② 当遇到 script 标签的时候会立即渲染一次。当 HTML 页面加载的过程中,遇到了一个 script 标签,如果之前已经加载了部分 HTML 内容,那么会先将之前加载的 HTML 内容渲染出来,然后再去加载对应的 javascript 脚本。
二、script 标签优化
script 标签默认是同步加载的,但是其提供了一些属性可以变成异步加载,如: async、defer、type=“module”
① async: 异步加载对应的 javascript 脚本,不阻塞 HTML 页面的渲染,当对应的 javascript 加载完成后,如果此时 HTML 页面还未加载完成,那么会阻塞页面的渲染,等 javascript 执行完成后再继续 HTML 页面的加载。
② defer: 异步加载对应的 javascript 脚本,不阻塞 HTML 页面的渲染,当对应的 javascript 加载完成后,如果此时 HTML 页面还未加载完成,那么不会阻塞页面的渲染,等 HTML 页面加载完成后再接着执行加载完成的 javascript 脚本。
③ type=“module”: 也是能起到异步加载的效果,效果同 defer,不过其可以配合 async 属性让 javascript 加载完成后立即执行。