Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么是多个';失败';当多个';然后';处理程序被链接到延迟?_Javascript_Jquery_Jquery Deferred_Promise - Fatal编程技术网

Javascript 为什么是多个';失败';当多个';然后';处理程序被链接到延迟?

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

我的项目涉及使用多API的工作流,这些API返回延迟承诺。我正在使用jQuery1.8

我知道
.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,但不能包装/更改错误