检测脚本列表是否全部加载到javascript中(使用命名空间)。

时间:2012-03-22 17:53:29

标签: javascript jquery html closures javascript-namespaces

我为javascript创建了一个名称空间框架。我正在加载一些动态添加到HTML的插件(.js文件)。

我将尝试简化代码。

此函数用于动态加载JS。加载.js文件后调用回调函数。请考虑以下代码已经运行。

MYNAMESPACE.plugins = ["plugin1", "plugin2"];
MYNAMESPACE.getJS = {
    get: function (url, callback) {
        var script = document.createElement("script");
        var head = document.getElementsByTagName('head')[0];
        script.type = "text/javascript";
        script.src = url;
        head.insertBefore(script, head.firstChild)
        script.onload = callback;
        script.onreadystate = callback;
        return script;
        }
};

我有一个init函数,可以加载MYNAMESPACE.plugins中包含的插件,如下所示:

MYNAMESPACE.init = function (callback) {
    for (index in MYNAMESPACE.plugins) {
        plugin = MYNAMESPACE.plugins[index];
        MYNAMESPACE.getJS.get(plugin + '.js', function ()
         {
              // This callback is executed when the js file is loaded
         });
    }
    // Here I want to execute callback function, but after all the callbacks in the for loop have been executed.  Something like: if (alljsloaded) callback();
}

在我的HTML中,我有以下脚本标记:

<html>
    <head>
    <script type="text/javascript">
        $(document).ready(function () {
            MYNAMESPACE.init(); 

            // The following line is not executed correctlybecause init finished before the scripts are loaded and the functionOnPlugin1 is undefined.
            MYNAMESPACE.functionOnPlugin1();
        });
    </script>
    </head>
    <body>
    </body>
</html>

我想改变这样的事情:

<html>
    <head>
    <script type="text/javascript">
        $(document).ready(function () {
            MYNAMESPACE.init(function() { MYNAMESPACE.functionOnPlugin1(); });  
        });
    </script>
    </head>
    <body>
    </body>
</html>

但我不知道如何修改函数MYNAMESPACE.init(),以便在加载所有插件脚本后执行回调。

有什么想法吗?也许使用闭包。

2 个答案:

答案 0 :(得分:3)

  1. 使用for(;;)循环播放数组 for(.. in ..)
  2. 在函数中创建一个计数器,每次加载脚本时都递增计数器。当它达到脚本数量时,调用回调函数。
  3. 代码:

    MYNAMESPACE.init = function (callback) {
        var allPluginsLength = MYNAMESPACE.plugins.length;
        var loadedCount = 0;
        if (allPluginsLength === 0) callback(); // No plugins, invoke callback.
        else for (var index=0; index<allPluginsLength; i++) {
            plugin = MYNAMESPACE.plugins[index];
            MYNAMESPACE.getJS.get(plugin + '.js', function () {
                  // This callback is executed when the js file is loaded
                  if (++loadedCount == allPluginsLength) {
                      callback();
                  }
             });
        }
    }
    

    此外,更改您的getJS.get方法。目前,callback总是在状态改变时执行,这是不可取的。为防止回调执行两次,可以使用以下命令:

        script.onload = function() {
            callback && callback();
            callback = false;
        };
        // onreadystatechange instead of onreadystate, btw.
        script.onreadystatechange = function() {
            if (this.readyState == 'complete') {
                callback && callback();
                callback = false;
            }
        };
    
    • callback && callback()用于确保存在回调。如果是,则调用它。
    • 调用回调后,会立即将其删除(callback = null) 这是必要的,因为在加载脚本时可以触发onloadonreadystatechange事件。如果没有我建议的代码,将为单个脚本多次调用回调。

答案 1 :(得分:1)

这样的一些变化应该有效:

MYNAMESPACE.init = function (callback) {
    var remaining = MYNAMESPACE.plugins.length;
    for (index in MYNAMESPACE.plugins) {
        plugin = MYNAMESPACE.plugins[index];
        MYNAMESPACE.getJS.get(plugin + '.js', function ()
         {
              // This callback is executed when the js file is loaded
              remaining = remaining - 1;
              if (remaining === 0)
              {
                  callback();
              }
         });
    }
}