概观
你有几个选择。 您可以使用回调来使用这些函数看起来像这样的代码:
getStuff(function(results) {
getMoreStuff(results, doSomethingWithStuff);
});
或者像这样,使用jQuery的Deferred和Promise对象:
getStuff().then(getMoreStuff).then(doSomethingWithStuff):
使用回调
getStuff和getMoreStuff接受一个参数,这个参数在完成后调用,例如:
function getStuff(callback) {
// ^------------------------------ callback argument
$.ajax({
...
success: function(results) {
// other functions involving results
callback(results);
// ^------------------------------------ use the callback arg
}
});
}
...和getMoreStuff类似。
使用Deferred和Promise
jQuery的ajax功能与其Deferred和Promise功能集成在一起。 您只需将return添加到现有功能即可实现,例如:
function getStuff(callback) {
return $.ajax({
...
});
}
(注意:无需success回调。)
然后这段代码:
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
做这个:
getStuff启动其ajax调用并返回调用创建的Promise 。
当该ajax调用完成并解析promise时,将调用getMoreStuff ,并将ajax调用的结果作为其第一个参数。 它开始了它的 ajax调用。
当getMoreStuff的ajax调用完成时,将调用doSomethingWithStuff并调用该调用的结果( getMoreStuff )。
then使用,而不是done ,以便在每个阶段获得正确的结果是很重要的。 (如果你使用done , getMoreStuff 和 doSomethingWithStuff都会看到getStuff的ajax调用的结果。)
这是使用ajax的完整示例:
function getStuff() {
display("getStuff starting ajax")
return $.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from first request"}'},
dataType: "json"
});
}
function getMoreStuff(results) {
display("getMoreStuff got " + results.message + ", starting ajax");
return $.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from second request"}'},
dataType: "json"
});
}
function doSomethingWithStuff(results) {
display("doSomethingWithStuff got " + results.message);
}
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
输出:
getStuff starting ajax
getMoreStuff got data from first request, starting ajax
doSomethingWithStuff got data from second request
你不需要使用ajax来获得这个好处,你可以使用自己的Deferred和Promise对象,这样你就可以编写如下链:
one().then(two).then(three);
...对于您可能有异步完成的任何情况。
这是一个非ajax示例:
function one() {
var d = new $.Deferred();
display("one running");
setTimeout(function() {
display("one resolving");
d.resolve("one");
}, 1000);
return d.promise();
}
function two(arg) {
var d = new $.Deferred();
display("Two: Got '" + arg + "'");
setTimeout(function() {
display("two resolving");
d.resolve("two");
}, 500);
return d.promise();
}
function three(arg) {
var d = new $.Deferred();
display("Three: Got '" + arg + "'");
setTimeout(function() {
display("three resolving");
d.resolve("three");
}, 500);
return d.promise();
}
one().then(two).then(three);
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
输出:
one running
one resolving
Two: Got 'one'
two resolving
Three: Got 'two'
three resolving
必要时可以组合这两个( ajax示例和非ajax示例)。 例如,如果我们从ajax示例中获取getStuff ,并且我们决定在将数据getMoreStuff给getMoreStuff之前必须对数据进行一些处理,我们就会改变它: Fiddle
function getStuff() {
// Create our own Deferred
var d = new $.Deferred();
display("getStuff starting ajax")
$.ajax({
url: "/echo/json/",
type: "POST",
data: {json: '{"message": "data from first request"}', delay: 1},
dataType: "json",
success: function(data) {
// Modify the data
data.message = "MODIFIED " + data.message;
// Resolve with the modified data
d.resolve(data);
}
});
return d;
}
请注意,我们如何使用它并没有改变:
getStuff().then(getMoreStuff).then(doSomethingWithStuff);
所有改变都在getStuff 。
这是关于整个“承诺”概念的一个伟大的事情(它完全不是jQuery特有的,但jQuery为我们提供了方便的版本),它非常适合解耦。