Javascript 为什么是多个';失败';当多个';然后';处理程序被链接到延迟?
我的项目涉及使用多API的工作流,这些API返回延迟承诺。我正在使用jQuery1.8 我知道Javascript 为什么是多个';失败';当多个';然后';处理程序被链接到延迟?,javascript,jquery,jquery-deferred,promise,Javascript,Jquery,Jquery Deferred,Promise,我的项目涉及使用多API的工作流,这些API返回延迟承诺。我正在使用jQuery1.8 我知道.done()和.then()之间的区别在于.then()返回一个新的承诺。在我的示例中,我希望如果第一个延迟被拒绝,那么只有第一个.fail()处理程序将被执行,因为第二个被链接到新的承诺。在执行过程中,两个失败处理程序都被执行 var firstDeferred = $.Deferred(), secondDeferred = $.Deferred(); firstDeferred.promise
.done()
和.then()
之间的区别在于.then()
返回一个新的承诺。在我的示例中,我希望如果第一个延迟被拒绝,那么只有第一个.fail()
处理程序将被执行,因为第二个被链接到新的承诺。在执行过程中,两个失败处理程序都被执行
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');
我的预期结果:
> first deferred object
实际结果:
> first deferred object
> first deferred object
为什么同时调用
.fail()
处理程序?如何构造工作流,使处理程序仅在特定的延迟承诺被拒绝时才被调用?发生这种情况是因为然后
返回一个新承诺(该结果通过管道传输到其回调返回的承诺的结果)
承诺可以有两种最终状态:已解决或失败。因此,由于第一个延迟失败,第二个延迟永远无法解决,因此它失败了。如果然后没有冒泡失败,你会发现自己有一个无限期等待的承诺。这可能是内存泄漏的风险
如果您只希望在函数实际运行时运行它,则只需更改管理然后失败函数的方式。发生这种情况的原因是然后
返回一个新承诺(该结果通过管道传输到其回调返回承诺的结果)
承诺可以有两种最终状态:已解决或失败。因此,由于第一个延迟失败,第二个延迟永远无法解决,因此它失败了。如果然后没有冒泡失败,你会发现自己有一个无限期等待的承诺。这可能是内存泄漏的风险
如果您只希望在then()
回调函数实际运行时运行该函数,则只需更改管理该函数的方式。您没有将任何内容链接到在then()
回调函数中返回的承诺,因为该回调函数从未执行过
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');
then()
接受以下参数:
then( doneFilter , failFilter )
回调是第一个参数,因此它是doneFilter
。但是第一个承诺失败了,因此then()
不会调用您的回调。它将调用failFilter
,但您不会为第二个参数传递任何内容
引述自:
如果所使用的筛选函数为null或未指定,则将使用与原始值相同的值解析或拒绝承诺
由于没有给出failFilter
参数,then()
只是转发第一个承诺的状态,这将触发第二个fail()
处理程序
这项工作:
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');
哪些日志:
first deferred object
second deferred object
您没有将任何内容链接到then()
回调中返回的承诺,因为该回调永远不会执行
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');
then()
接受以下参数:
then( doneFilter , failFilter )
回调是第一个参数,因此它是doneFilter
。但是第一个承诺失败了,因此then()
不会调用您的回调。它将调用failFilter
,但您不会为第二个参数传递任何内容
引述自:
如果所使用的筛选函数为null或未指定,则将使用与原始值相同的值解析或拒绝承诺
由于没有给出failFilter
参数,then()
只是转发第一个承诺的状态,这将触发第二个fail()
处理程序
这项工作:
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');
哪些日志:
first deferred object
second deferred object
jquery的deferred并不是一个很好的promise impl,我建议使用符合promises/a+()的impl。在jQuery中,您可以使用then
方法附加一个错误处理程序(第二个参数,不能使用fail
),使用此函数,您可以返回一个值,该值将传递给下一级的successHandler,但是您不能包装/更改错误(可能在承诺/a+impl中)或完全阻止错误。承诺必须通过错误或成功来完成。Gene C,如果链接两个.fail()
处理程序,则将触发两个失败处理程序,除非链中的两个失败处理程序之间存在某种差异,以提供具有不同状态的新承诺。“某物”必须是正确编写的.then()
。如上所述,当拒绝firstDeferred
时,没有第二个参数的中间.then()
将无效;“失败”状态将直接通过传播。然后()
第二个处理程序将触发。失败()
处理程序将触发,正如您所观察到的那样。@David McMullin,您所说的不是100%正确。jQuery的.then()
允许从其任何一个处理程序返回一个新的承诺,从而允许沿着链传递的状态独立于从其左侧馈送.then()
的承诺。但是.then()
处理程序并不总是以这种方式运行。返回非承诺将传播原始承诺的状态,但已使用返回值解决/拒绝。没有返回语句的处理程序将导致传播原始承诺而不进行更改。在不同的承诺之间移动确实很困难。@Beetroot谢谢你提供的额外信息!我在一个沙箱中进行测试,从未想过要尝试回报另一个承诺,非常感谢您指出out=)@DavidMcMullin,您应该看到我尝试使用Q。。。。。不太妙:(jquery的deferred不是一个很好的promise impl,我建议使用符合promises/a+()的impl。在jquery中可以做的是,使用then
方法附加一个错误处理程序(第二个参数,不能使用fail
),使用此函数可以返回一个值,该值将传递给下一级的successHandler,但不能包装/更改错误