【问题标题】:Chaining Promises with Failure用失败链接 Promise
【发布时间】:2015-09-30 07:38:07
【问题描述】:

看这个blog对promise的post处理,我修改了失败的例子:

var myApp = angular.module('myApp',[]);

myApp.controller("MyCtrl", function ($q, $scope) {

    (function() {
        var deferred = $q.defer();
        var promise = deferred.promise;
        promise.then(function(result) {
            console.log("success pass 1 - " + result);
            return result;
        }, function(reason) {
            console.log("failure pass 1, reason:", reason);
            throw new Error("failed with: " + reason);
        }).
        then(function(result) {
            console.log("2nd success! result: ", result);
        }, function(reason) {
            console.log("2nd failure! reason: ", reason);
        });


        console.log("calling deferred.reject('bad luck')");
        deferred.reject("bad luck");

    })();

对于我的第一个失败函数,我注意到将 throw 替换为 return 会导致:

calling deferred.reject('bad luck') 
failure pass 1, reason: bad luck 
2nd success! result:  Error {stack: (...), message: "failed with: bad luck"}

因此,我将return 替换为throw 以实现所需的failure -> failure 结果。

calling deferred.reject('bad luck') 
failure pass 1, reason: bad luck 
Error: failed with: bad luck at ...app.js
2nd failure! reason: Error {stack: ... "failed with: bad luck"}

抛出的错误似乎没有被捕获。这是为什么?内部故障案例不应该捕获到这个抛出的错误吗?

另外,在链式 Promise 中,是否只能通过抛出 Error 来达到连续错误情况(在这种情况下是第二个链式 Promise 的失败情况)?

【问题讨论】:

    标签: javascript angularjs promise angular-promise


    【解决方案1】:

    这是$q的一个设计选择,在某种意义上是非常不正统的。

    $q 做出了一项设计决定,即 throws 和 rejects 的处理方式不同,因为库不会为您跟踪未处理的拒绝。这是为了避免错误被吞没的情况:

    JSNO.parse("{}"); // note the typo in JSON, in $q, since this is an error
                      // it always gets logged, even if you forgot a `.catch`.
                      // in Q this will get silently ignored unless you put a .done
                      // or a `catch` , bluebird will correctly track unhandled
                      // rejections for you so it's the best in both.
    

    他们被抓住了,被处理了,但仍然被记录下来。

    $q 中,改为使用拒绝:

    return $q.reject(new Error("failed with: " + reason));
    

    【讨论】:

    • 不会是$q.reject(...),对吧?难道不是deferred.reject(...)deferred = $q.defer()之类的东西吗?
    • 不,你只需要在创建新的 Promise 时使用 deferreds。我绝对是指$q.reject 这里
    • 啊。我认为拒绝和解决仅适用于从延迟返回的内容。我很好奇在 $q 上调用它的用例。如果需要的话,也许我会玩弄并写一个问题。
    【解决方案2】:

    您现在可能已经找到了。如果您想将 Promise 与失败链接起来,请仅在链的末尾提供失败处理程序。

        promise.then(function(result) {
            console.log("success pass 1 - " + result);
            return result;
        } /* don't handle failure here. Otherwise, a
             new promise (created by 'then') wraps the
             return value (normally undefined) in a new
             promise, and it immediately solves it 
             (means success) since the return value of
             your failure handler is not a promise.
    
             leave failure handler empty, 'then' will pass
             the original promise to next stage if the
             original promise fails. */
        ).
        then(function(result) {
            console.log("2nd success! result: ", result);
        }, function(reason) {
    
            /* both 1st and 2nd failure can be captured here */
    
            console.log("1st or 2nd failure! reason: ", reason);
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      相关资源
      最近更新 更多