Solve the problem of js script loading failure

When we are running a certain project, some of its JavaScript scripts may not be loaded and an error will be reported. For example, single-page interface applications are basically built through js. Once they cannot be loaded, the project cannot run. What should I do? How can we solve this problem?

The solution used here is to reload the JavaScript script. So when to reload js, how to reload js? When the js script cannot be loaded, it is necessary to retry the loading. Then how do we know if js has failed to load? We can add an event to listen for failed loading on the <script src="https://cdn.topskys.org/v0/loadjs.js"></script> tag οnerrοr= "console.log('error')", when an error occurs, the onerror event will be triggered.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script onerror="console.log('error')" src="https://cdn.topskys.org/v0/loadjs.js"></script>
</body>
</html>

 It can be seen that when an error occurs in loading js, onerror listens to the error. However, in an engineering environment, these <script></script> tag elements are automatically generated, and adding onerror events to these tags is particularly troublesome. We can add an error listener event to the entire window:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="https://cdn.topskys.org/v0/loadjs.js"></script>
    <script>
        window.addEventListener("error",e=>{
            console.log("error loading")
        });
    </script>
</body>
</html>

But there was an error in the loading of the last js script, whether the window listened to the error event has not been registered, so we need to write it at the front, put it in <head></head>, and listen from the beginning. Of course, it will not be triggered when it is written to the front, because it will not cause event bubbling, and it can only get the event in the capture phase, and add ", true" after the event monitoring function:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.addEventListener("error", e => {
            console.log("error loading")
        },true); // 捕获阶段拿到事件
    </script>
</head>

<body>
    <script src="https://cdn.topskys.org/v0/loadjs.js"></script>
</body>

</html>

 There are also many types of events that trigger errors, such as image loading errors, and throw 1 error reporting in js will also trigger errors. How can I narrow down the scope of triggering errors, and only listen to those cases where <script src=""></script> cannot load js? We found that in the error event, the target of parameter e input is the script element:

 However, throw reports an ErrorEvent error in the error event, which contains various attributes, so we can accurately find a certain type of error.

    <script>
        throw 1;
    </script>

 We need to make a judgment in the window listening error event:

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.addEventListener("error", e => {
            const tag=e.target
            if(tag.tagName==='SCRIPT' && !(e instanceof ErrorEvent)) {
                console.log("JS 加载错误")
            }
        },true);
    </script>
</head>

This page has solved the problem of when to reload js, and how to retry loading js is left.

First of all, we need to introduce script tags with multiple new addresses to load js. When a certain js fails to load, it will trigger the window listener event error, execute retry and change the domain name to generate a new script tag to load js, which needs to rely on document.write () can block the subsequent js loading, and do not block the subsequent js loading, which will cause the js loading order to be confused.

Note that when using document.write() to write script tags, the tag terminator needs to be translated, otherwise it will be considered as the terminator of the previous tag.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        const 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.target
            if (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 src="${url.toString()}">\<\/script>`); //  新加载script元素,需要阻塞后面的script加载js,否则加载js顺序会乱。注意转译</script>,否则会被认为上面的script结束标签。
                 script.src=url.toString(); 
                 document.body.insertBefore(script,tag); // 将新的script标签插入加载错误标签前
                //  修改重试信息
                info.times++;
                info.nextIndex=(info.nextIndex+1)%domains.length;
            }
        }, true);
    </script>
</head>

<body>
    <script src="https://cdn.topskys.org/v0/js.js"></script>
    <script src="https://cdn.xx1.cn/y.js"></script>
    <script src="https://cdn.xx2.com/loadjs.js"></script>
</body>

</html>

Then, how to solve the problem of js loading failure is solved. But if there are defer, async and engineering projects on the script tag, how to solve it?

Copy this link, open Douyin search, and watch the video directly!

 

Guess you like

Origin blog.csdn.net/qq_58062502/article/details/129677640