我有一个相当复杂的异步函数系列,我在jQuery Deferreds的帮助下进行链接。
本质上我有两个并行的函数流,其次是在并行流完成时应该串行执行的函数。这是一个例子(它们是现实生活中的AJAX调用):
function makeOmelette() {
$.when(
crackEggs().then(beatEggs),
washTomatos().then(chopTomatos)
).then(mixEggsAndTomatos).then(fryEggsAndTomatos).done(function() {
msg('Omelette is ready!');
}).fail(function() {
msg('Oh no, omelette fail!');
});
}
最后的done()和fail()处理程序处理成功或失败。我希望fail()处理程序在出现任何错误时立即执行,链中的任何位置以及所有进一步执行都要停止。
大多数情况下,这是有效的 - 除了一个案例。如果在打蛋时出现故障,那么即使在这些任务开始之前已经发生故障,西红柿仍然会被清洗和切碎。同样,如果在洗西番茄时出现故障,这并不能阻止crackEggs和beatEggs功能运行。
您可以看到an example here。
我对此的关注是,在我的现实代码中,我不希望浏览器对服务器进行AJAX调用,这可能会改变状态,如果没有意义,因为整个过程有已经失败了。
有没有办法做我想要的?我想我可以单独为每个并行任务附加失败处理程序,但我想知道是否有更简洁/重复的方式。
谢谢!
答案 0 :(得分:0)
向状态添加变量。例如,在done( var status = 1 )
内部和fail( var status = 2
内部,然后在并行函数运行之前添加一个简单的语句,以便在status = 2
时不会运行。
答案 1 :(得分:0)
尝试(此模式)
HTML
<input type="button" value="reject" />
<input type="button" value="resolve" /> <output></output> <output></output>
<div id="messages"></div>
JS
$(function () {
$("input").on("click", function (e) {
var dfd = new $.Deferred();
$("#messages").children().remove();
makeOmelette(this.value);
function makeOmelette(resolveReject, dfd) {
// dfd = dfd;
$.when(
// `crackEggs("resolve")`, `crackEggs("reject")`
crackEggs(resolveReject),
washTomatos())
.done(function (a, b) {
if (a === "rejected") {
err();
};
if (a === "resolved") {
beatEggs();
chopTomatos();
mixEggsAndTomatos();
fryEggsAndTomatos();
success();
};
});
};
function success() {
dfd.done(function (s) {
msg('Omelette is ready!');
$("output:first").val(s);
})
};
function err() {
dfd.fail(function (e) {
msg('Oh no, omelette fail!');
$("output:first").val(e);
});
};
dfd.always(function () {
$("output:last").val(dfd.state() + " at " + $.now())
});
function crackEggs(_resolveReject) {
(_resolveReject === "reject"
? dfd.reject(_resolveReject + " called at " + $.now())
: dfd.resolve(_resolveReject + " called at " + $.now())
);
msg('Cracking eggs');
return dfd.state();
}
function beatEggs() {
msg('Beating eggs');
return dfd.state();
}
function washTomatos() {
msg('Washing tomatos');
return dfd.state();
}
function chopTomatos() {
msg('Chopping tomatos');
return dfd.state();
}
function mixEggsAndTomatos() {
msg('Mixing eggs and tomatos');
return dfd.state();
}
function fryEggsAndTomatos() {
msg('Frying eggs and tomatos');
return dfd.state();
}
function msg(text) {
$('#messages').append('<p>' + text + '</p>');
}
});
});