简体   繁体   English

当几个“ then”处理程序链接到一个延迟的处理程序时,为什么要调用多个“ fail”处理程序?

[英]Why are multiple 'fail' handlers being called when several 'then' handlers are chained to a deferred?

My project involves workflows that uses muliple API's that return deferred promises. 我的项目涉及使用多个API的工作流,这些API返回延迟的Promise。 I am using jQuery 1.8 我正在使用jQuery 1.8

I understand that the difference between .done() and .then() is that .then() returns a new promise. 我知道.done().then()之间的区别在于.done() .then()返回一个新的Promise。 In my example, I would expect that if the first deferred was rejected, that only the first .fail() handler would be executed because the second is chained to the new promise. 在我的示例中,我希望如果第一个延迟的请求被拒绝,则仅第一个.fail()处理函数将被执行,因为第二个被链接到新的.fail() In execution, both fail handlers are executed. 在执行中,两个失败处理程序均被执行。

var firstDeferred = $.Deferred(), secondDeferred = $.Deferred();

firstDeferred.promise()
.fail(function (error) {
    console.log(error);
})
.then(function () {
    return secondDeferred.promise();
})
.fail(function (error) {
    console.log(error);
});

firstDeferred.reject('first deferred object');
//secondDeferred.reject('second deferred object');

My Expected Result: 我的预期结果:

> first deferred object

Actual Result: 实际结果:

> first deferred object
> first deferred object

Why are both .fail() handlers being called? 为什么两个.fail()处理.fail()都被调用? How can I structure my workflow in a way that the the handlers are only called when the specific deferred promises are rejected? 如何以仅当特定的延迟承诺被拒绝时才调用处理程序的方式构造工作流程?

You're not chaining anything to the promise you return in the then() callback, because that callback never gets executed. 您不会将任何内容链接到在then()回调中返回的承诺,因为该回调永远不会执行。

then() takes these arguments: then()接受以下参数:

then( doneFilter , failFilter )

Your callback is the 1st argument, hence it's the doneFilter . 您的回调是第一个参数,因此它是doneFilter But the first promise fails, so then() doesn't call your callback. 但是第一个承诺失败了,所以then()不会调用您的回调。 It would call the failFilter , but you don't pass anything for that 2nd argument. 调用failFilter ,但是您不会为第二个参数传递任何内容。

Quoting from the docs : 文档引用:

If the filter function used is null, or not specified, the promise will be resolved or rejected with the same values as the original. 如果使用的过滤器函数为null或未指定,则将以与原始值相同的值来解析或拒绝promise。

And since the failFilter argument isn't given, then() just forwards the state of the first promise, which triggers the 2nd fail() handler. 并且由于未提供failFilter参数, then()只会转发第一个承诺的状态,从而触发第二个fail()处理程序。

This works: 这有效:

var firstDeferred  = $.Deferred(),
    secondDeferred = $.Deferred();

firstDeferred.promise()
.fail(function (error) {
    console.log(error);
})
.then(null, function () { // Notice the null
    return secondDeferred.promise();
})
.fail(function (error) {
    console.log(error);
});

firstDeferred.reject('first deferred object');
secondDeferred.reject('second deferred object');

which logs: 哪个日志:

first deferred object
second deferred object 

This happens because then return a new promise (which result is piped to the result of its callback returned promise). 发生这种情况是因为then返回了一个新的Promise(该结果通过管道传递到其回调返回的Promise的结果)。

A promise can have two final state: resolved or failed. 一个承诺可以有两个最终状态:已解决或失败。 So, as the first deferred failed, the second can never be resolved, so it fails. 因此,由于第一个延迟失败,因此第二个无法解决,因此它失败了。 If then wasn't bubbling the failing, you'd found yourself with an indefinitely pending promise. 如果then不是失败的冒泡,那么您将发现自己有无限期的未决承诺。 This could be a risk for memory leaks. 这可能会导致内存泄漏。

Just changed the way you manage the then fail function if you only want it to be run if it has actually run. 只是更改了管理then失败功能的方式,如果您只希望它在实际运行时才运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM