> ## Content Index
> Fetch the complete content index at: https://iiong.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# JavaScript异步加载脚本
- URL: https://iiong.com/javascript-asyn-load-script/
- Published: 2018-11-04T12:40:58.000Z
- Updated: 2026-06-22T15:31:47.000Z
- Description: 在Nuxt.js打包时候发现vendors文件实在是太大，看了官方文档发现新版又不支持老的Api。
- Author: 淮城一只猫
- Tags: 奇技淫巧, Web 前端

### Cap1 前言

在Nuxt.js打包时候发现`vendors`文件实在是太大，看了官方文档发现新版又不支持老的Api，所以寻找一上午也没找到很好的方案，目前把一些类库文件抽取出来直接CDN加载就行，但原本以为这是很简单事情，可是中间又遇到不少问题，例如脚本和脚本直接的依赖关系等。

### Cap2 HTML5

其实在HTML5也有相关的标签属性可以实现：

```javascript
<script src="//code.jquery.com/jquery-1.11.0.min.js" async></script>

```

async 属性规定一旦脚本可用，则会异步执行。

注释：async 属性仅适用于外部脚本（只有在使用 src 属性时）。

注释：有多种执行外部脚本的方法：

- 如果 async="async"：脚本相对于页面的其余部分异步地执行（当页面继续进行解析时，脚本将被执行）
- 如果不使用 async 且 defer="defer"：脚本将在页面完成解析时执行
- 如果既不使用 async 也不使用 defer：在浏览器继续解析页面之前，立即读取并执行脚本

### Cap3 编程方式

```javascript
(function() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.async = true;
    script.src = "//code.jquery.com/jquery-1.11.0.min.js";
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);
})();

```

这种动态插入脚本的方法基本上主流写法。

### Cap4 支持回调函数的编程方式

如果需要在插入脚本执行代码执行下一步操作：

```javascript
function loadScript(url, callback) {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.async = true;
    if (script.readyState) {
        script.onreadystatechange = function () {
            if (script.readyState == "loaded" || script.readyState == "complete") {
                script.onreadystatechange = null;
                if (callback && typeof callback === "function") {
                    callback();
                }
            }
        };
    } else {
        script.onload = function () {
            if (callback && typeof callback === "function") {
                callback();
            }
        };
    }
    script.src = url;
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(script);
}

```

理论上这样写法满足大量的需求了，但是在我这里遇到一个问题：

![](https://i.loli.net/2018/10/26/5bd2b9298dde5.jpg)

如果一层一层回调下去，岂不是难以解读。所以还需要一个更优雅的写法：

### Cap5 支持回调函数的ES8风格编程方式

```javascript
async function loadScripts (scripts) {
    function get (src) {
        return new Promise(function (resolve, reject) {
            var el = document.createElement("script");
            el.async = true;
            el.addEventListener("load", function () {
                resolve(src);
            }, false);
            el.addEventListener("error", function () {
                reject(src);
            }, false);
            el.src = src;
            (document.getElementsByTagName("head")[0] || document.getElementsByTagName("body")[0]).appendChild(el);
        });
    }
 
    const myPromises = scripts.map(async function (script, index) {
        return await get(script);
    });
 
    return await Promise.all(myPromises);
}

```

到上面脚本来看，无论哪方面都可以满足了：

```javascript
loadScripts([
    "https://static.zinoui.com/1.5/compiled/zino.svg.min.js",
    "https://static.zinoui.com/libs/jquery/jquery.min.js"
]).then(function () {
    return loadScripts(["https://static.zinoui.com/1.5/compiled/zino.chart.min.js"]);
}).then(function () {
    $("#chart").zinoChart(settings);
});

```