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

上一篇: jQuery Deferred continue to resolve after fail handler

下一篇: callback a promise in AngularJs with $q?