0

私は、独自のかなり単純な JavaScript ローダー メカニズムを構築しようとしています。これを改善するライブラリがたくさんあることは知っていますが、自分で試してみることで何かを学ぶことができると思いました。

以下は私の(簡略化された)コードです。私の目的は、すべての異なる js ファイル (モッズ) への参照を 1 つの場所 (_Modsオブジェクト) に保持することです。_Modsスクリプト タグが読み込まれると、コードがリッスンするカスタム イベントが送信され、(オブジェクトからの) 独自の mod データがパラメーターとして渡されます。そのカスタム イベントを受信するたびに、その mod が読み込まれたことを示すフラグを立て、最終的にはすべての mod が読み込まれたことを示す計画でした。そして次に進みます。

私の問題は、このコードを実行すると、コンソールがmod 'word' loaded!一度印刷されてから終了することです。実行する!mod.callback.done前に条件をコメントアウトすると、3 回出力されます。callback()mod 'word' loaded!

したがって、modロードする必要があるすべての新しい mod に対して変数が再割り当てされ、スクリプトがロードされてそのコールバックを実行する必要があるときに、最初の 2 つの mod のデータ オブジェクトへのポインタが失われることに気付きました。

3 つの異なる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 に答える