使用顺序回调自动加载javascript文件

时间:2010-11-22 10:14:36

标签: javascript jquery iteration

我有以下javascript列表,此列表中的每个项目都有一个脚本文件url和一个回调函数,我想要做的是迭代这个列表,加载每个脚本,然后执行回调函数,并且 NOT 移动到下一个项目,除非当前回调已完成执行..


var data = { 
    scripts: [
        {
            file    : 'some-script.js',
            callback: function() {
                // do some code here
            },
        },
        {
            file    : 'another-script.js',
            callback: function() {
                // do some code here
            },
        },
        ...
    ]
};

如果可能,我该如何自动执行此操作?

4 个答案:

答案 0 :(得分:2)

(我假设您正在使用JSONP加载外部脚本)您将面临的问题是这些脚本不会同时加载所有脚本。

下面是一些代码,一旦加载了相关的脚本,它就会调用你的回调函数。

    function include_js(url, callback) {  // http://www.nczonline.net
        var script = document.createElement("script");
        script.type = "text/javascript";

        if (script.readyState) {  //IE
            script.onreadystatechange = function(){
                if (script.readyState == "loaded" || script.readyState == "complete"){
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else {  //Others
            script.onload = function(){
                callback();
            };
        }
        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

//Edit

    for (var i = 0; i < data.scripts.length; i++) {
         include_js(data.scripts[i].file, data.scripts[i].callback);
    }

答案 1 :(得分:1)

可能如果,您可以在每个脚本中测试一个符号,或者每个脚本在加载完成后都可以执行函数调用。

加载脚本很简单,我相信你知道:

var script = document.createElement('script');
script.src = /* ... the source path ... */;
document.body.appendChild(script);

(相反,您会看到有人追加到head;无关紧要,body很容易找到。)

但困难的部分是知道何时下载并执行。唯一真正的方法是通过轮询来查看脚本定义的新全局符号是否已定义,或者让脚本在加载完成后主动回叫(a'la JSONP)。 / p>

无论哪种方式,一旦您检测到符号或获得回调,您就可以继续加载下一个脚本。

这是一个快速而又脏的草图,它是在找到全局符号(window对象上的属性)的基础上进行的:

// The scripts to load
var scriptList = { 
    scripts: [
        {
            file    : 'some-script.js',
            callback: function() {
                // do some code here
            },
            symbol  : "someSymbol",
            timeout : 30000 // We know this one is slow, give it 30 seconds
        },
        {
            file    : 'another-script.js',
            callback: function() {
                // do some code here
            },
            symbol  : "anotherSymbol"
        },
        // ...
    ]
};

// Triggering the load
loadScripts(scriptList);

// Library routines to do the load
function loadScripts(list)
{
    var index, timeout;

    // Start with the first one (loadNextScript starts with an increment)
    index = -1;
    loadNextScript();

    // This function loads the next script in the list; if there are no
    // more, it simply returns
    function loadNextScript()
    {
        var script;

        // Are there more?
        ++index;
        if (index < list.length)
        {
            // Yes, append a `script` element
            script = document.createElement('script');
            script.src = list.file;
            document.body.appendChild(script);

            // Determine when to time out
            timeout = new Date() + (list[index].timeout || 20000); // Time out in Xms, default 20 seconds

            // Start polling
            setTimeout(pollForScript, 0); // Async, but almost immediately (4-10ms on most browsers)
        }
    }

    // This function polls to see if the current script has loaded yet by
    // checking for a global symbol it defines.
    function pollForScript()
    {
        var result;

        // Has it been too long?
        if (new Date() > timeout)
        {
            // Yes
            result = "timeout";
        }
        else
        {
            // Has the symbol been defined?
            if (typeof window[list[index].symbol] !== "undefined")
            {
                // Yes
                result = "loaded";
            }
            else
            {
                // Nope, keep waiting
                setTimeout(pollForScript, 250); // Check every quarter-second
            }
        }

        // Did we get a result?
        if (result)
        {
            // Yes, do the callback telling it of the result
            try {
                list[index].callback(result);
            }
            catch (e) {
            }

            // Load the next script
            loadNextScript();
        }
    }
}

答案 2 :(得分:0)

让回调调用你的loadTheNextScriptInList或任何函数。您可以通过向onLoad事件添加匿名函数来自动执行此操作。此匿名函数应首先调用列表中的回调集,然后调用loadTheNextScriptInList函数。

答案 3 :(得分:0)

这只是我写的快速和HAVENT TESTED,但它应该以递归的方式完成你的工作。希望这会有所帮助:

var data = { 
    scripts: [
        {
            file    : 'some-script.js',
            callback: function() {
                // do some code here
            },
        },
        {
            file    : 'another-script.js',
            callback: function() {
                // do some code here
            },
        },
        ...
    ]
};


$(document).ready(function() {

    if(data.scripts.length > 0) {
        scriptLoader(0);
    }

});

function scriptLoader(i) {


    var currScript = data.scripts[i];


    $.getScript(currScript.file, function() {

      // execute your callback
      currScript.callback();

      // load next script
      if(i < data.scripts.length) {
        scriptLoader(i++);
      }

    });

}

哦,顺便说一句,这使用了JQuery javascript框架,仅供参考。