当我们在运行某一个项目时,它的某些JavaScript脚本可能加载不出来,报错。像现在单页界面应用基本上都是通过js来构建,一旦加载不出,这个项目就不能运行了,那怎么办?我们如何解决这个问题?

这里采用的方案是,重新加载JavaScript脚本。那么什么时候去重新加载js,如何重新加载js?在js脚本加载不出来时,就需要去重试加载。那我们怎么知道js有没有加载失败,我们可以在标签上添加一个监听加载失败的事件 οnerrοr=”console.log(‘error’)”,当出现错误会触发onerror事件。

Document

可以看到,当加载js出现错误时,onerror监听到了错误。但是在工程化的环境,这些标签元素都是自动生成的,给这些标签添加上onerror事件,这种方式又特别麻烦。我们可以给整个window添加error监听事件:

Documentwindow.addEventListener("error",e=>{console.log("error loading")});

但上一个js脚本加载出现错误,window监听error事件还有没有注册,所以说我们需要把它写在最前边,放到里,一开始就去监听。当然,写到最前边它也不会触发,因为它不会事件冒泡,只能在捕获阶段就拿到该事件,在监听事件函数后加“, true”:

Documentwindow.addEventListener("error", e => {console.log("error loading")},true); // 捕获阶段拿到事件

触发error的事件类型也很多,如图片加载错误、在js中throw 1报错也会触发error。我么怎么样缩小触发error的范围,只监听到那些 加载js不出来的情况?我们发现error事件中,参数e输入的target是script元素:

但是呢,throw 在error事件里报的是ErrorEvent错误,里面包含各种属性,故我们可以准确地找到某一种错误。

throw 1;

我们需要在window监听error事件里面作一个判断:

Documentwindow.addEventListener("error", e => {const tag=e.targetif(tag.tagName==='SCRIPT' && !(e instanceof ErrorEvent)) {console.log("JS 加载错误")}},true);

到这里页面解决了,什么时候去重新加载js的问题,还剩下如何重试加载js。

首先,我们需要引入多个新地址的script标签加载js,当某一个js加载失败时,就会被触发window监听事件error,执行重试更换域名生成新的script标签加载js,需要靠document.write()才能阻塞后面的js加载,不阻塞后续js加载,会造成js加载顺序混乱。

注意,在使用document.write()写入script标签时,需要对标签结束符进行转译,否则会被认为是上个标签的结束符。

Documentconst domains = ["https://cdn.topskys.org/v0", "https://cdn.topskys1.org/v1", "https://cdn.topskys2.org/v2"]; // 重试域名数组const maxRetry=3; // 最多重试次数 const retryInfo={}; // 记录重试次数及下一个重试的域名数组下标{times:1,nextIndex:2}window.addEventListener("error", e => {const tag = e.targetif (tag.tagName === 'SCRIPT' && !(e instanceof ErrorEvent)) {// console.log("JS 加载错误")const url=new URL(tag.src) // 拿到script标签的src域名if(!retryInfo[url.pathname]){retryInfo[url.pathname]={times:0,nextIndex:0,}}const info=retryInfo[url.pathname]; // 取出文件路径 ./loadjs.js ./js.js ./y.js const script=document.createElement("script") url.host=domains[info.nextIndex]; // 更换域名 document.write(`\`); //新加载script元素,需要阻塞后面的script加载js,否则加载js顺序会乱。注意转译,否则会被认为上面的script结束标签。 script.src=url.toString();document.body.insertBefore(script,tag); // 将新的script标签插入加载错误标签前//修改重试信息info.times++;info.nextIndex=(info.nextIndex+1)%domains.length;}}, true);

那么,如何解决js加载失败的问题就解决了。但如果script标签上有defer、async及工程化项目中呢,有如何该解决” />复制此链接,打开Dou音搜索,直接观看视频!