我有一个可以解决或拒绝的承诺 . 我想在这些情况下做一些具体的事情,然后继续解决承诺链(基本上我想“ grab ”被拒绝的承诺,做一些事情,然后继续解决) .
这是一个功能代码片段,显示了我遇到的问题:
var def = $.Deferred();
def.then(
function() {
console.log('first success handler');
},
function() {
console.log('first fail handler');
return $.Deferred().resolve();
}
);
def.then(
function() {
console.log('second success handler');
},
function() {
console.log('second fail handler');
}
);
def.done(function() {
console.log('done handler');
});
def.reject();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
预期结果 :
first fail handler
second success handler
done handler
目前的结果:
first fail handler
second fail handler
根据jQuery文档:
从jQuery 1.8开始,deferred.then()方法返回一个新的promise,它可以通过函数[...]过滤延迟的状态和值 . 这些过滤器函数可以返回一个新值以传递给promise的.done()或.fail()回调,或者它们可以返回另一个可观察对象(Deferred,Promise等),它将传递其已解析/拒绝的状态和值承诺的回调 .
所以我不知道为什么这不起作用 . 我期望在第一个失败处理程序中返回已解析的promise以允许其余的promise链继续解析 .
3 回答
模式......
...形成两个(或更多)分支,每个
then()
仅依赖于def
. 每个分支都具有独立的过滤功能,但它没有被利用 .这与......非常不同
...形成单链(没有分支) . 第一个
then()
依赖于def
,第二个then()
依赖于第一个then()
. 这里,第一个then()
的过滤能力通过链接另一个then()
(等等)来利用 .因此,您将通过将问题中的代码转换为第二个模式来获得预期的输出:
简而言之,这就是承诺链接的全部意义 .
但是不要忘记完全分支 . 在某些情况下,这是至关重要的 . 例如,在this answer中,
batchRequests()
返回_p
,它可以被调用者(即一个分支)进一步链接,但也会与_p.then(..., ...)
形成自己的专用分支 . 完全遵循它 - 它相当复杂 - 现在相信我,分支是解决方案的重要组成部分 .文档的重要部分是
然而,你扔掉了那个返回值,并在原始的
def
上调用了下一个.then(…)
.你会想要使用
你的代码实际上在做的是排队两个处理程序(通过
then
函数) . 当延期被拒绝时,它不能再被改变 .当Deferred被拒绝时,第一个
then
处理程序将触发写入您的第一个控制台消息 .第
return $.Deferred().resolve();
行将创建一个新的已解决的Deferred,但它不会"return"到您的第二个then
,因为该处理程序已经绑定到第一个Deferred实例 .因此,您的第二个
then
处理程序现在也将触发failFilter(Deferred被拒绝时的处理程序) .您可以采取的一种方法是在拒绝(或解决)延期时传递一个值 . 然后,您可以收到该响应并采取补救措施,如此(有点人为的)样本所示:
我知道无法在两个
then
处理程序之间插入,它们只是两个排队的处理程序到同一个Deferred .