0

我正在尝试构建我自己的一个相当简单的 javascript 加载器机制。我知道有很多库做得更好,但我认为我可以通过自己尝试来学习一些东西。

下面是我的(简化的)代码。我的目标是将所有不同 js 文件(mod)的引用保存在一个地方,即_Mods对象。加载脚本标签后,它将发送代码监听的自定义事件,并以自己的 mod 数据(来自_Mods对象)作为参数。每次收到该自定义事件时,计划将该模块标记为已加载,并最终声明所有模块已加载。然后继续。

我的问题是,当我运行此代码时,控制台将打印mod 'word' loaded!一次然后退出。如果我在运行之前注释掉!mod.callback.done条件,callback()它将打印mod 'word' loaded!三遍。

因此,我意识到该mod变量会为每个应该加载的新模块重新分配,并且在加载脚本并应该进行回调时,指向前两个模块数据对象的指针丢失了。

有什么建议我可以重构它以便从三个不同的mod 中获取回调?

(function(window) {
    var ModLoader = (function() {
        var _Mods = {
            game: {
                name: "game",
                src: "js/GameEngine.js"
            },
            dictionary: {
                name: "dictionary",
                src: "js/Dictionary.js"
            },
            word: {
                name: "word",
                src: "js/Word.js"
            }
        },

        _loadMods = function() {
            var head = document.getElementsByTagName('HEAD').item(0);
            for (var property in _Mods) {
                if (_Mods.hasOwnProperty(property)) {
                    var mod = _Mods[property],
                        scriptTag = document.createElement("script");
                    scriptTag.setAttribute("type", "text/javascript");
                    scriptTag.src = mod.src;

                    mod.callback = function() {
                        var customEvent = document.createEvent("Events");
                        customEvent.initEvent("ModLoaded", true, true);
                        customEvent.mod = mod;
                        window.dispatchEvent(customEvent);
                    };

                    scriptTag.onreadystatechange = scriptTag.onload = function() {
                        var state = scriptTag.readyState;
                        if (!mod.callback.done && (!state || /loaded|complete/.test(state))) {
                            mod.callback.done = true;
                            mod.callback();
                        }
                    };

                    (document.body || head).appendChild(scriptTag);    
                }
            }
        },

        _modLoaded = function(event) {
            console.log("mod '" + event.mod.name + "' loaded!");
        };

        return {
            loadMods: _loadMods,
            modLoaded: _modLoaded
        };
    })();

    window.addEventListener("ModLoaded", ModLoader.modLoaded, false);

    ModLoader.loadMods();

})(window);
4

1 回答 1

1

尝试这样的事情:

scriptTag.onreadystatechange = scriptTag.onload = (function(mod) {
    return function(){
        var state = scriptTag.readyState;
        if (!mod.callback.done && (!state || /loaded|complete/.test(state))) {
            mod.callback.done = true;
            mod.callback();
        }
    };
})(mod);
于 2013-09-13T05:55:31.863 回答