Подтвердить что ты не робот

Использование getScript синхронно

Я пишу движок, который требует использования getScript довольно широко. Я просто включил его в свою собственную функцию, для удобства использования, но теперь мне нужно убедиться, что сама функция является синхронной. К сожалению, я не могу заставить getScript ждать, пока загрузится script, на самом деле закончит загрузку, прежде чем продолжить. Я даже пытался установить для jQuery ajax asynch свойство false, прежде чем делать вызов. Я думаю об использовании протокола jQuery when/done, но я, похоже, не могу обойти логику размещения его внутри функции и сделать эту функцию синхронной. Любая помощь будет очень оценена!

function loadScript(script){
//Unrelated stuff here!!!
$.when(
$.getScript(script,function(){
    //Unrelated stuff here!!!
})).done(function(){
    //Wait until done, then finish function
});
}

Код цикла (по запросу):

for (var i in divlist){
        switch($("#"+divlist[i]).css({"background-color"})){
            case #FFF:
            loadScript(scriptlist[0],divlist[i]);
            break;
        case #000:
            loadScript(scriptlist[2],divlist[i]);
            break;
        case #333:
            loadScript(scriptlist[3],divlist[i]);
            break;
        case #777:
            loadScript(scriptlist[4],divlist[i]);
            break;
    }
}
4b9b3361

Ответ 1

Как я уже сказал, относительно легко связывать вызовы Ajax с обеими объектами. Теперь он не видит, почему сценарии должны загружаться один за другим, но у вас есть причина для этого.

Сначала, хотя я бы избавился от оператора switch, если вы вызываете только одну и ту же функцию с разными аргументами. Например. вы можете поместить все URL-адреса script в карту:

var scripts = {
    '#FFF': '...',
    '#000': '...'
    // etc.
};

Вы можете связать promises, просто вернув другое обещание от обратного вызова, переданного в .then [docs]. Все, что вам нужно сделать, это начать с обещания или отложенного объекта:

var deferred = new $.Deferred();
var promise = deferred.promise();

for (var i in divlist) {
    // we need an immediately invoked function expression to capture
    // the current value of the iteration 
    (function($element) {
        // chaining the promises, 
        // by assigning the new promise to the variable
        // and returning a promise from the callback
        promise = promise.then(function() {
            return loadScript(
                scripts[$element.css("background-color")], 
                $element
            );
        });
    }($('#' + divlist[i])));
}

promise.done(function() {
    // optional: Do something after all scripts have been loaded
});

// Resolve the deferred object and trigger the callbacks
deferred.resolve();

В loadScript вы просто возвращаете обещание, возвращенное из $.getScript или возвращаемое .done:

function loadScript(script_url, $element){
    // Unrelated stuff here!!!

    return $.getScript(script_url).done(function(){
        //  Unrelated stuff here
        // do something with $element after the script loaded.
    });
}

Все сценарии будут вызваны в порядке доступа в цикле. Обратите внимание, что если divlist является массивом, вы должны использовать обычный цикл for вместо цикла for...in.

Ответ 2

Это сработало для меня и может помочь вам.

$.ajax({
    async: false,
    url: "jui/js/jquery-ui-1.8.20.min.js",
    dataType: "script"
});

В принципе, я просто обошел сокращенную нотацию и добавил в async: false

Ответ 3

Знаете ли вы, что $.getScript принимает функцию обратного вызова, которая вызывается синхронно после загрузки script?

Пример:

$.getScript(url,function(){
//do after loading script
});

У меня есть еще два решения: чистый js один и один для нескольких js-загрузок.

Ответ 4

Попробуйте этот способ, создайте массив с отложенными объектами и используйте $.when с "apply"

var scripts = [
    'src/script1.js',
    'src/script2.js'
];

var queue = scripts.map(function(script) {
    return $.getScript(script);
});

$.when.apply(null, queue).done(function() {
    // Wait until done, then finish function
});

Ответ 5

var getScript = function(url) {
    var s = document.createElement('script');
    s.async = true;
    s.src = url;
    var to = document.getElementsByTagName('script')[0];
    to.parentNode.insertBefore(s, to);
};

Ответ 6

Просто создайте script node, установите его свойство src в JS, который хотите загрузить, затем добавьте его в голову:

var myScript = document.createElement('script');
myScript.src = "thesource.js";
document.head.appendChild(myScript);

Ответ 7

вот что я делаю

function loadJsFile(filename) {
    $.ajaxSetup({
        cache: true
    });

    var dloadJs = new $.Deferred();
    $.when(dloadJs).done(function () {
        $.ajaxSetup({
            cache: false
        });
    });

    dloadJs.resolve(
         $.getScript(filename, function () { })
    );
}