JavaScript文件的同步和異步加載

對於JS文件的引用,儘管當前有很多框架和工具(好比webpack,commonjs,requiresjs等)都作了很好的處理。可是拋開這些框架,瞭解原生的加載方式仍是不無裨益。本文簡述一些js文件的同步和異步加載方式。javascript

同步加載

可在html文件裏以<script>標籤插入,這是初學時最基本的方式。html

準備兩個js文件以下:
calc1.jsjava

console.log('calc1 loading begin')

function add(...args) {
    return args.reduce((currentTotal, i) => currentTotal + i, 0);
}

console.log('calc1 loading end')

calc2.jswebpack

console.log('calc2 loading begin')

console.log(add(1,2,3))

console.log('calc2 loading end')

calc2.js 是依賴calc1.js的。git

html文件以下:github

<body>

    <script src="calc1.js">
    </script>
    
    <script src="calc2.js">
    </script>
</body>

這種方式下,文件加載是同步的。即calc1.js加載完成後,才加載calc2.js,因此保證了calc2.js總能正確地調用calc1裏的add函數。在Chrome裏的調試結果以下:
圖片描述web

但同步加載的缺點也明顯,若是有多個文件的時候,所有加載時間會很長,並且阻塞用戶界面響應。app

經過Script Element異步加載

異步加載的優勢是,可以同時加載多個js文件,並且因爲是異步,不會阻塞用戶界面,用戶體驗好。固然缺點是,不能保證有依賴關係的文件的加載順序。框架

html 代碼異步

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        var script1 = document.createElement('script');
        script1.src='calc1.js';
        script1.type='text/javascript';

        var script2 = document.createElement('script');
        script2.src='calc2.js';
        script2.type='text/javascript';

        document.getElementsByTagName('head')[0].appendChild(script1).appendChild(script2);
    </script>
</head>

在Chrome裏的調試結果有時候能正確的輸出以下:
圖片描述

但有時候因爲clac1.js沒有被先加載,calc2.js執行時會報錯。
圖片描述

那麼咱們就得須要解決加載順序問題,保證calc1.js先加載。

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        function loadScript(file, callbackFn) {
            var script = document.createElement('script');
            script.src= file;
            script.type='text/javascript';
            // 監聽onload時間,當前js文件加載完成後,再加載下一個
            script.onload = callbackFn;
            document.getElementsByTagName('head')[0].appendChild(script)
        }
        
        loadScript('calc1.js', function () {
            loadScript('calc2.js');
        } );

    </script>
</head>

這樣就能永遠輸出正確結果了。

經過 AJAX 加載JS文件

<script>
        function loadScript(file, callbackFn) {
            var xhr = new XMLHttpRequest();
            xhr.open('get', file, true);
            // for IE
            if (xhr.onreadystatechange) {
                xhr.onreadystatechange = function () {
                    console.log(xhr.readyState, xhr.status);
                    if (xhr.readyState == 4) {
                        if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                            insertScriptText(xhr.responseText);
                            if (callbackFn) {
                                callbackFn();
                            }
                        }
                    }
                }
            } else {
                xhr.onload = function () {
                    insertScriptText(xhr.responseText);
                    if (callbackFn) {
                        callbackFn();
                    }
                }
            }
            xhr.send(null);
        }

        function insertScriptText(scriptText) {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.text = scriptText;
            document.body.appendChild(script);
        }

        loadScript('calc1.js', function () {
            loadScript('calc2.js');
        });

    </script>

也能正確的輸出結果。
圖片描述

總結

若是是單一或少數js文件,能夠在html body的最後插入script標籤,以同步方式加載。Webpack其實也是把多個js文件合併稱一個,而後在body插入script引用。

若是是多個js文件,建議異步加載,以免阻塞界面渲染,也縮短總體加載時間。本文介紹了script element和Ajax兩種方式,而且對於有依賴關係的文件加載順序,也作了實例。請參考 https://github.com/JackieGe/a...

相關文章
相關標籤/搜索