Использование 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;
}
}
Ответы
Ответ 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 () { })
);
}