Динамично загружающийся JavaScript синхронно

Я использую шаблон модуля, одна из вещей, которые я хочу сделать, динамично включают внешний файл JavaScript, выполняют файл и затем используют функции/переменные в файле в return { } из моего модуля.

Я не могу выяснить, как сделать это легко. Есть ли какие-либо стандартные способы выполнить псевдо синхронную внешнюю загрузку сценария?

function myModule() {
    var tag = document.createElement("script");
    tag.type = "text/javascript";
    tag.src = "http://some/script.js";
    document.getElementsByTagName('head')[0].appendChild(tag);

    //something should go here to ensure file is loaded before return is executed

    return {
        external: externalVariable 
    }
}

58
задан 21 May 2010 в 08:10

2 ответа

У меня была подобная задача несколькими днями ранее, и вот то, как я сделал это.
Этот загрузчик работает и в file:// префиксы, а также в http:// и https:// и является совместимым перекрестным браузером.
Это однако, не может загрузить определенные классы или функции как модули из сценариев; это загрузит целый сценарий в целом и сделает это доступным для DOM.

// Loads a script or an array of scripts (including stylesheets)
// in their respective index order, synchronously.
// By Sayanjyoti Das @https://stackoverflow.com/users/7189950/sayanjyoti-das
var Loader={
    queue: [], // Scripts queued to be loaded synchronously
    loadJsCss: function(src, onl) {
        var ext=src.toLowerCase().substring(src.length-3, src.length);
        if(ext=='.js') {
            var scrNode=el('script', null, null, null);
            scrNode.type='text/javascript';
            scrNode.onload=function() {onl();};
            scrNode.src=src;
            document.body.appendChild(scrNode);
        }else if(ext=='css') {
            var cssNode=el('link', null, null, null);
            cssNode.rel='stylesheet';
            cssNode.type='text/css';
            cssNode.href=src;
            document.head.appendChild(cssNode);
            onl();
        }
    },
    add: function(data) {
        var ltype=(typeof data.src).toLowerCase();

        // Load a single script
        if(ltype=='string') {
            data.src=data.src;
            Loader.queue.splice(0, 1, data, Loader.queue[0]);
            Loader.next();
        }
        // Load an array of scripts
        else if(ltype=='object') {
            for(var i=data.src.length-1; i>=0; i--) {
                Loader.queue.splice(0, 1, {
                    src: data.src[i],
                    onload: function() {
                        if(Loader.next()==false) {
                            data.onload();
                            return;
                        }
                        Loader.next();
                    }
                }, Loader.queue[0]);
            }
            Loader.next();
        }
    },
    next: function() {
        if(Loader.queue.length!=0 && Loader.queue[0]) {
            var scr=Loader.queue[0];

            // Remove the script from the queue
            if(Loader.queue.length>1)
                Loader.queue.splice(0, 2, Loader.queue[1]);
            else
                Loader.queue=[];

            // Load the script
            Loader.loadJsCss(scr.src, scr.onload);
        }else return false;
    }
};

вышеупомянутая функция очень мощна и изящна ; это позволяет Вам загружать единственный сценарий или массив сценария синхронно (т.е., следующий сценарий, не загруженный до предыдущей законченной загрузки сценария). Кроме того, загруженный сценарий может загрузить больше сценариев, который задерживает очередь в родительском сценарии.

BTW, сценарий здесь означает файл JavaScript или таблицу стилей CSS .

Вот то, как использовать Примечание it:-

// Load a single script
Loader.add({
    src: 'test.js',
    onload: function() {
        alert('yay!');
    }
});

// Load multiple scripts
Loader.add({
    src: ['test1.js', 'test2.js', 'mystyles.css', 'test3.js'],
    onload: function() {
        alert('all loaded!');
    }
});

, что, эти onload функция в аргументах Загрузчика вызвана, когда весь из сценариев загрузились, не, когда один или единственный сценарий загружается.

можно также загрузить больше сценариев в сценариях, которые Вы загрузили, такой как в test.js, test1.js, и т.д. Путем выполнения этого, Вы задержите загрузку следующего родительского сценария, и очередь в дочернем сценарии будет расположена по приоритетам.

Hope это помогает :-)

0
ответ дан 1 November 2019 в 14:05

вот мой код

var loaded_script = [];
function loadScript(urls, callback, sync) {
    var len = urls.length, count = 0;

    // check are all js loaded, then execute callback (if any)
    var check = function() {
        if (count == len) {
            callback && typeof callback=="function" && callback();
        }
    };

    for (var i = 0; i < len; i++) {
        var url = urls[i];

        // check if script not loaded (prevent load again)
        if (loaded_script.indexOf(url) == -1) {
            var script = document.createElement("script");
            script.type = "text/javascript";

            // set sync loading here (default is async)
            if (sync) {
                script.async = false;
            }

            // script onload event
            if (script.readyState) {    // IE
                script.onreadystatechange = function() {
                    if (script.readyState=="loaded" || script.readyState=="complete") {
                        script.onreadystatechange = null;
                        count++, check();
                    }
                };
            } else {    // Others
                script.onload = function() {
                    count++, check();
                };
            }

            // add script to head tag
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);

            // mark this script has loaded
            loaded_script.push(url);
        } else {
            count++, check();
        }
    }
}

, я использую это на pjax сайте.

loadScript(
    [
        "js/first.js",
        "js/second.js",
    ],
    function() {
        alert("Scripts loaded.");
    },
    true
);
0
ответ дан 1 November 2019 в 14:05

Другие вопросы по тегам:

Похожие вопросы: