jQuery Deferred在失败处理程序后继续解析
我有一个可以解决或拒绝的承诺。 我想在这些情况下做一些具体的事情,然后继续解决诺言链(基本上我想“抓住”被拒绝的诺言,做点什么,然后继续解决)。
这是一个功能片段,显示我遇到的问题:
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>
模式...
var def = $.Deferred();
def.then(successHandler, errorHandler);
def.then(successHandler, errorHandler);
// etc.
...形成两个(或更多)分支, then()
每个分支仅依赖于def
。 每个分支拥有独立的过滤能力,但没有被利用。
这与......截然不同
var def = $.Deferred();
def.then(successHandler, errorHandler).then(successHandler, errorHandler); // etc.
...形成单链(无分支)。 第一个then()
依赖于def
,第二个then()
依赖于第一个then()
。 这里,第一个then()
的过滤能力是通过链接另一个then()
(等等then()
来利用的。
因此,您将通过将问题中的代码转换为第二种模式来获得预期的输出:
var def = $.Deferred();
def.then(function() {
console.log('first success handler');
}, function() {
console.log('first fail handler'); // (1)
return $.Deferred().resolve();
}).then(function() {
console.log('second success handler'); // (2)
}, function() {
console.log('second fail handler');
}).done(function() {
console.log('done handler'); // (3)
});
def.reject();
简而言之,这就是承诺链接的全部内容。
但不要忘记完全分支。 在某些情况下,这是至关重要的。 例如,在这个答案中, batchRequests()
返回_p
,它可以被调用者(这是一个分支)进一步链接,但也使用_p.then(..., ...)
形成它自己的私人分支。 如果无法完全遵循它,请不要担心 - 现在相当复杂 - 现在请相信我,分支是解决方案的重要组成部分。
文档的重要部分是
deferred.then()
方法返回一个新的承诺
然而,你正在扔掉那个返回值,并且在原来的def
上调用了下一个.then(…)
。
你会想要使用
var p = $.Deferred().reject().promise();
p.then(function() {
console.log('first success handler');
}, function() {
console.log('first fail handler');
return $.Deferred().resolve();
}).then(function() {
//^^^^^ chain directly on the result
console.log('second success handler');
}, function() {
console.log('second fail handler');
}).then(function() {
//^^^^^
console.log('done handler');
});
你的代码有效地做的是排队两个处理程序(通过then
功能)。 当延期被拒绝时,它不能再被改变。
当延迟被拒绝时,第一个then
处理程序触发写你的第一个控制台消息。
该行return $.Deferred().resolve();
将创建一个新的解决推迟,但它不是“回归”编辑你的第二个then
因为该处理器已被拴在第一递延实例。
因此,你的第二个then
处理器将现在火还击中failFilter(处理程序时,递延被拒绝)。
您可以采取的一种方法是在拒绝(或解决)您的延期时传递一个值。 然后,您可以收到该回复并采取补救措施,如以下(有些人为的)示例所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="test"></div>
<script>
var def = $.Deferred();
def.then(
function () {
console.log('first success handler');
},
function (response) {
console.log('first fail handler');
console.log(response);
}
);
def.then(
function () {
console.log('second success handler');
},
function (response) {
if (response === 999) {
// do something to recover from earlier reject
console.log('recovery action initiated');
} else {
console.log('second fail handler');
}
}
);
def.done(function () {
console.log('done handler');
});
def.reject(999);
</script>
</body>
</html>
链接地址: http://www.djcxy.com/p/55459.html