2016-01-06 3 views
5

A previous question revealed how to load in jQuery using native JavaScript. Я успешно использовал код обратного вызова из ответа там, тиражируемых здесь:Load JQuery с JavaScript, используя Promises

// Anonymous "self-invoking" function 
(function() { 
    // Load the script 
    var script = document.createElement("SCRIPT"); 
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'; 
    script.type = 'text/javascript'; 
    document.getElementsByTagName("head")[0].appendChild(script); 

    // Poll for jQuery to come into existance 
    var checkReady = function(callback) { 
     if (window.jQuery) { 
      callback(jQuery); 
     } 
     else { 
      window.setTimeout(function() { checkReady(callback); }, 100); 
     } 
    }; 

    // Start polling... 
    checkReady(function($) { 
     // Use $ here... 
    }); 
})(); 

Как я могу сделать то же самое с помощью native JavaScript Promises?

Причина Я спрашиваю, потому что мне внезапно нужно отключиться от более раннего обратного вызова, и это ужасный «беспорядок». Я надеюсь, что обещания - лучший способ, и у меня нет реального интереса к использованию платформы загрузчика.

Вот что у меня до сих пор, но обещание всегда заканчивается отвергнуто: (. Я извиняюсь заранее за мое полное невежество)

// This code doesn't work quite right. 
// Poll for jQuery to come into existance using a Promise 
var jQueryReady = new Promise(
    function(resolve, reject) { 

     // Load jQuery 
     var script = document.createElement('SCRIPT'); 
     script.type = 'text/javascript'; 
     script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'; 
     document.getElementsByTagName('head')[0].appendChild(script); 

     if (window.jQuery) { 
     resolve("YAY"); 
     } else { 
     reject("UGH"); 
     } 
    }); 

jQueryReady.then(
    function(success) { 
    console.log(success); 
    }, 
    function(error) { 
    console.error("Really helpful error:", error); 
    }); 

+0

Вам нужно будет продолжить использовать старый код и разрешить обещание только при готовности jquery. В этом случае нет необходимости отклонять его, если jquery не загружается через некоторое время. –

ответ

5

Вот версия, что делает простую loadScript() функции, которая возвращает обещание, а затем предоставляет обертку вокруг него, который определяет, является ли уже загружено JQuery:

function loadScript(url) { 
    return new Promise(function(resolve reject) { 
     var script = document.createElement("script"); 
     script.onload = resolve; 
     script.onerror = reject; 
     script.src = url; 
     document.getElementsByTagName("head")[0].appendChild(script); 
    }); 
} 

function loadjQuery() { 
    if (window.jQuery) { 
     // already loaded and ready to go 
     return Promise.resolve(); 
    } else { 
     return loadScript('https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'); 
    } 
} 


// Usage: 
loadjQuery().then(function() { 
    // code here that uses jQuery 
}, function() { 
    // error loading jQuery 
}); 

Заметки о коде:

  1. В первом блоке кода, устанавливая один таймер и предполагая, что сценарий будет загружен, когда этот таймер срабатывает, это похоже на рулетку. Это может работать большую часть времени, но это не чисто надежный способ делать что-то. Кроме того, чтобы быть в безопасности, вы должны установить таймер на более длительный период времени, чем это обычно необходимо. Вместо этого вы должны запускать на основе обратного вызова onload сценария. Тогда вы точно узнаете, когда скрипт готов со 100% -ной надежностью.

  2. В вашем втором кодовом блоке версия вашего обещания успешно обрабатывает случай, когда jQuery уже загружен, а затем rejects(), когда jQuery должен быть настроен под заказ. Как вы можете видеть из моего примера, вам понадобится resolve(), когда новый загруженный тег скрипта завершит загрузку, чтобы ваше обещание работало по желанию.

+0

Очень полезно, особенно с абстрактной функцией 'loadScript()' в случае, если мне понадобится перетащить другие скрипты в будущем! И спасибо за заметки о существующем коде - у меня определенно были проблемы с моими знаниями в этих областях. – Rydash

0

скрипты вставляются в страницу таким образом выполняются асинхронно. (См. "Dynamically importing scripts" на MDN.) В результате window.jQuery всегда будет undefined.

Попробуйте подключить обработчик onload к элементу скрипта, чтобы разрешение Promise выполнялось только после выполнения сценария.

Например (перед установкой script.src):

script.onload = function() { 
    if (window.jQuery) { 
     resolve("YAY"); 
    } else { 
     reject("UGH"); 
    } 
}; 

Как обычно, этот метод не совместим со всеми браузерами. Проверьте this post out на способы их размещения.

0

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

Это возможное решение:

var jQueryReady = new Promise(
    function(resolve, reject) { 

    // Load jQuery 
    var script = document.createElement('SCRIPT'); 
    script.type = 'text/javascript'; 
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'; 
    document.getElementsByTagName('head')[0].appendChild(script); 

    // You should also have a timeout in case your script never loads 
    var timeoutHandler = setTimeout(10000, function() { 
     if (checkIntervalHandler) clearInterval(checkIntervalHandler); 
     reject("UGH"); 
    }); 

    var checkIntervalHandler = setInterval(500, function() { 
     if (window.jQuery) { 
     if(timeoutHandler) clearTimeout(timeoutHandler); 
     resolve("YAY"); 
     } 
    }); 
}); 
Смежные вопросы