14

我有这个将脚本加载到当前 DOM 中的简单函数:

function loadscripts ( async ) {
    if( async === undefined ) {
        async = false;
    }

    var scripts = [];
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js'];

    for(var s in _scripts) {
        scripts[s] = document.createElement('script');
        scripts[s].type = 'text/javascript';
        scripts[s].src = _scripts[s];
        scripts[s].async = async;

        document.getElementsByTagName('head').appendChild( scripts[s] );
    }
}

它们加载良好,没有错误。我知道以编程方式加载脚本时有事件处理程序:

  • onreadystatechange
  • 加载

现在我想做以下事情:

  • 从数组加载第一个脚本,当事件处理程序完成时加载下一个,依此类推(递归)。

抱歉,我没有在我的函数中提供onreadystatechangeandonload事件。

4

5 回答 5

17

我会这样做:

LoadScripts();

function LoadScripts(async)
{
    if( async === undefined ) {
        async = false;
    }
    var scripts = [];
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js'];

    if(async){
        LoadScriptsAsync(_scripts, scripts)
    }else{
        LoadScriptsSync(_scripts,scripts)
    }
}

// what you are looking for :
function LoadScriptsSync (_scripts, scripts) {

    var x = 0;
    var loopArray = function(_scripts, scripts) {
        // call itself
        loadScript(_scripts[x], scripts[x], function(){
            // set x to next item
            x++;
            // any more items in array?
            if(x < _scripts.length) {
                loopArray(_scripts, scripts);   
            }
        }); 
    }
    loopArray(_scripts, scripts);      
}

// async load as in your code
function LoadScriptsAsync (_scripts, scripts){
    for(var i = 0;i < _scripts.length;i++) {
        loadScript(_scripts[i], scripts[i], function(){});
    }
}

// load script function with callback to handle synchronicity 
function loadScript( src, script, callback ){

    script = document.createElement('script');
    script.onerror = function() { 
        // handling error when loading script
        alert('Error to handle')
    }
    script.onload = function(){
        console.log(src + ' loaded ')
        callback();
    }
    script.src = src;
    document.getElementsByTagName('head')[0].appendChild(script);
}
于 2013-03-08T11:09:00.087 回答
1

试试这个:

function loadscripts ( async ) {
    if( async === undefined ) {
        async = false;
    }

    var scripts = [];
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js'];
    for(var s in _scripts) {
        scripts[s] = document.createElement('script');
        scripts[s].type = 'text/javascript';
        scripts[s].src = _scripts[s];
        scripts[s].async = async;
    }
    var loadNextScript = function() {
        var script = scripts.shift();
        var loaded = false;
        document.getElementsByTagName('head').appendChild( script );
        script.onload = script.onreadystatechange = function() {
            var rs = this.readyState;
            if (rs && rs != 'complete' && rs != 'loaded') return;
            if (loaded) return;
            loaded = true;
            if (scripts.length) {
                loadNextScript();
            } else {
                // done
            }
        };
    };
    loadNextScript();
}
于 2013-03-08T10:46:23.923 回答
1

你可以用这样的承诺来做到这一点。

// loads an individual script
var loadScript = function (path) {
    // generate promise
    return new Promise(function (fulfill, reject) {
        // create object
        var script = document.createElement('script');

        // when it loads or the ready state changes
        script.onload = script.onreadystatechange = function () {
            // make sure it's finished, then fullfill the promise
            if (!this.readyState || this.readyState == 'complete') fulfill(this);
        };

        // begin loading it
        script.src = path;

        // add to head
        document.getElementsByTagName('head')[0].appendChild(script);
    });
};

// this is the one you want
var loadScripts = function (scripts) {
    return scripts.reduce(function (queue, path) {
        // once the current item on the queue has loaded, load the next one
        return queue.then(function () {
            // individual script
            return loadScript(path);
        });
    }, Promise.resolve() /* this bit is so queue is always a promise */);
};

用法:

getScripts(["foo.js", "bar.js"]).then(function () {
    // whatever you want to happen when it's all done
});

但是它不做任何错误处理,所以如果你需要它,你必须实现它。

于 2015-04-14T22:38:59.623 回答
1

必须按给定的 x、y、z 顺序加载脚本,因为我只有几个。这种方法对我有用。无法将它们加载到身体或头部,因为它们很大而且我使用的是静态登录页面。

document.addEventListener('DOMContentLoaded', function(event) {
        // initial DOM loaded
        var vendorJS = document.createElement('script');
        vendorJS.src = 'assets/vendor.js';

        var appJS = document.createElement('script');
        appJS.src = 'assets/application.js';

        var envJS = document.createElement('script');
        envJS.src = 'assets/env.js';

        document.body.appendChild(vendorJS);

        vendorJS.onload = vendorJS.onreadystatechange = function() {
            document.body.appendChild(appJS);

            appJS.onload = appJS.onreadystatechange = function() {
                document.body.appendChild(envJS);
            };
        };
});
于 2016-11-01T14:07:12.973 回答
-1

我们可以使用lab.min.js在html中一个接一个地加载脚本。

该库以同步方式运行。

<script>
var _DIR_ = "js/vendor/";

    $LAB.setOptions({
        AlwaysPreserveOrder: true
    });
    $LAB
        .queueScript(_DIR_ + 'jquery-v2-1-3.min.js')
        .queueWait()
        .queueScript(_DIR_ + 'angular.min.js')
        .queueWait()
        .queueScript(_DIR_ + 'socket.io-1.3.5.js')
        .queueScript(_DIR_ + 'angular-bootstrap/ui-bootstrap-tpls.min.js')
        .queueScript(_DIR_ + 'Angular plugins/angular-ui-notification.min.js')
        .runQueue();
</script>
于 2019-05-07T13:50:31.247 回答