在load事件期间注入的脚本是否阻止其他加载事件处理程序?

时间:2018-04-11 15:55:27

标签: javascript performance

假设的第三方JS供应商提供此脚本以包含在每个页面中:

(function() {
    function loadAsync(){
        // Inject the script.
        var script = document.createElement('script'); 
        script.type = 'text/javascript';
        script.src = 'https://example.com/3rdPartyStuff.js';

        // Find a reasonable place to inject the script.
        var firstScript = document.getElementsByTagName('script')[0]; 
        firstScript.parentNode.insertBefore(script, firstScript);
    }

    // Attach the script loader to the load event.
    if (window.attachEvent) { 
        window.attachEvent('onload', loadAsync); 
    } else { 
        window.addEventListener('load', loadAsync, false); 
    }
})();

其他加载事件处理程序是否必须等待此脚本下载并执行才能继续,或者其他JS可以运行直到此脚本可用并准备执行?

这个问题的答案是否因浏览器而异?

1 个答案:

答案 0 :(得分:1)

正如Pointy和Patrick在评论中解释的那样,在任何注入的脚本执行之前,load事件会完全显示出来。我写了一个演示版,在Chrome,IE和Edge中确认了这一点(之后我停止了测试)。

在JSFiddle上测试它:https://jsfiddle.net/bhh7szyh/3/

简而言之,我不必担心第三方脚本会减慢加载事件的速度。

Patrick还描述了使用async属性添加的脚本的行为:

  

动态注入脚本的默认行为是,如果未设置async,则异步加载,但将其设置为false将导致现代浏览器同步执行。

测试代码:

<!DOCTYPE html>
<html>
    <head>

        <title>Tests</title>

        <script>

            (function() {

                function sleep(milliseconds) {
                    var start = new Date().getTime();
                    for (var i = 0; i < 1e7; i++) {
                        if ((new Date().getTime() - start) > milliseconds){
                            break;
                        }
                    }
                }

                function loadAsync(url){
                    // Inject the script.
                    var script = document.createElement('script'); 
                    script.type = 'text/javascript';
                    script.src = url;

                    // Find a reasonable place to inject the script.
                    var firstScript = document.getElementsByTagName('script')[0]; 
                    firstScript.parentNode.insertBefore(script, firstScript);
                }

                function attach_to_load(fn) {
                    if (window.attachEvent) { 
                        window.attachEvent('onload', fn); 
                    } else { 
                        window.addEventListener('load', fn, false); 
                    }
                }

                attach_to_load(function() { sleep(5000); console.log('before injected JS'); });

                attach_to_load(function() { loadAsync('https://pastebin.com/raw/g40BS6Tg') });

                attach_to_load(function() { sleep(5000); console.log('after injected JS'); });

            })();

        </script>

    </head>

    <body>

        <h1>Tests Happened</h1>

    </body>

</html>