jQuery $.when 不等待延迟链完成 ajax 调用
jQuery $.when does not wait for deferred chain to complete ajax calls
这里我尝试顺序加载几个JS文件。问题是 $.when
没有等待链完成。但最后一个 $.Deferred.then
按预期工作。我应该怎么做才能使 $.when
工作?
var urls = [
"https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js"
];
var xxx = $.Deferred();
xxx.then(function() {
options = {
dataType: "script",
url: urls[0],
cache: false
};
return $.ajax(options).promise();
})
.then(function() {
options = {
dataType: "script",
url: urls[1],
cache: false
};
return $.ajax(options).promise();
})
.then(function() {
options = {
dataType: "script",
url: urls[2],
cache: false
};
return $.ajax(options).promise();
}).then(function() {
$("body").append("This is correct. All files are loaded.<br>");
});
$.when(xxx).done(function() {
$("body").append("This is wrong. JS files are not loaded yet.<br>");
});
xxx.resolve();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
您的方法无效,因为您从同一个承诺创建了两个分支。你有相当于:
var xxx = $.Deferred();
xxx.then(...).then(...); // promise chain 1
xxx.then(...) // promise chain 2
xxx.resolve(); // start the race between the two promise chains
这只是两个未排序或协调的独立承诺链之间的竞赛。执行时间短的那个会先结束。它们之间的协调度为零。
有关进一步说明,请参阅 and 。
而且,您对 $.when(xxx).done()
的使用是不必要的,根本不是问题的一部分。使用 xxx.done()
.
会得到相同的结果
您可以只使用一个承诺链来修复它:
p.then(...).then(...).then(...)
然后,一切都按正确顺序和协调进行。
var urls = [
"https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js"
];
let options = {
dataType: "script",
url: urls[0],
cache: false
};
$.ajax(options).then(function() {
let options = {
dataType: "script",
url: urls[1],
cache: false
};
return $.ajax(options);
}).then(function() {
let options = {
dataType: "script",
url: urls[2],
cache: false
};
return $.ajax(options).then(function() {
$("body").append("Last script loaded<br>");
});
}).then(function() {
$("body").append("This is correct. All files are loaded.<br>");
});
工作示例:https://jsfiddle.net/jfriend00/tLp68a3q/
或者,如果您仍想使用 var xxx = $.Deferred()
初始化您的链,以便稍后使用 xxx.resolve()
启动它,那么您也可以这样做,但您不能使用 xxx.then()
或 $.when(xxx)
因为那是一个完全独立的分支,根本没有链接到其他承诺链。
以 $.Deferred()
开头的工作示例:https://jsfiddle.net/jfriend00/y5n3hb99/
这里我尝试顺序加载几个JS文件。问题是 $.when
没有等待链完成。但最后一个 $.Deferred.then
按预期工作。我应该怎么做才能使 $.when
工作?
var urls = [
"https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js"
];
var xxx = $.Deferred();
xxx.then(function() {
options = {
dataType: "script",
url: urls[0],
cache: false
};
return $.ajax(options).promise();
})
.then(function() {
options = {
dataType: "script",
url: urls[1],
cache: false
};
return $.ajax(options).promise();
})
.then(function() {
options = {
dataType: "script",
url: urls[2],
cache: false
};
return $.ajax(options).promise();
}).then(function() {
$("body").append("This is correct. All files are loaded.<br>");
});
$.when(xxx).done(function() {
$("body").append("This is wrong. JS files are not loaded yet.<br>");
});
xxx.resolve();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
您的方法无效,因为您从同一个承诺创建了两个分支。你有相当于:
var xxx = $.Deferred();
xxx.then(...).then(...); // promise chain 1
xxx.then(...) // promise chain 2
xxx.resolve(); // start the race between the two promise chains
这只是两个未排序或协调的独立承诺链之间的竞赛。执行时间短的那个会先结束。它们之间的协调度为零。
有关进一步说明,请参阅
而且,您对 $.when(xxx).done()
的使用是不必要的,根本不是问题的一部分。使用 xxx.done()
.
您可以只使用一个承诺链来修复它:
p.then(...).then(...).then(...)
然后,一切都按正确顺序和协调进行。
var urls = [
"https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe.js",
"https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.2/photoswipe-ui-default.js"
];
let options = {
dataType: "script",
url: urls[0],
cache: false
};
$.ajax(options).then(function() {
let options = {
dataType: "script",
url: urls[1],
cache: false
};
return $.ajax(options);
}).then(function() {
let options = {
dataType: "script",
url: urls[2],
cache: false
};
return $.ajax(options).then(function() {
$("body").append("Last script loaded<br>");
});
}).then(function() {
$("body").append("This is correct. All files are loaded.<br>");
});
工作示例:https://jsfiddle.net/jfriend00/tLp68a3q/
或者,如果您仍想使用 var xxx = $.Deferred()
初始化您的链,以便稍后使用 xxx.resolve()
启动它,那么您也可以这样做,但您不能使用 xxx.then()
或 $.when(xxx)
因为那是一个完全独立的分支,根本没有链接到其他承诺链。
以 $.Deferred()
开头的工作示例:https://jsfiddle.net/jfriend00/y5n3hb99/