【问题标题】:How to stop/break in the middle of chained promises如何在链式承诺中停止/中断
【发布时间】:2014-11-16 11:28:46
【问题描述】:

我有一个对服务器的 $http 调用链。如果一个呼叫失败,我想向用户显示通知并停止链。起初我以为我可以使用 $q.reject 来停止链,但事实证明程序流程继续到下一个then 的错误处理程序。我也尝试过不返回任何内容,但流程仍在继续。

我可以停止流中链吗?所以例如下面的脚本应该打印result: |A|D|F而不是result: |A|D|F|E|H|J

如果无法在链中停止流,我必须在每个then 的错误处理程序中添加额外的条件,还是有更优雅的方式?

angular.module("MyModule", []).controller("MyCtrl", ["$scope", "$q", "$timeout",
    function($scope, $q, $timeout) {
        $scope.result = "";
        var d0 = $q.defer();
        $timeout(function() {
            d0.reject("A");       // the promise will fail
        }, 1000);
        d0.promise.then(
            function(response) {
                $scope.result += "|" + response + "|B";
                var d1 = $q.defer();
                $timeout(function() {
                    d1.resolve("C");
                }, 1000);
                return d1.promise;
            },
            function(response) {
                $scope.result += "|" + response + "|D";
                return $q.reject("E");
            }
        ).finally(                // it should stop here ...
            function() { $scope.result += "|F"; }
        ).then(
            function(response) {
                $scope.result += "|" + response + "|G";
            },
            function(response) {  // ... but instead it continues here
                $scope.result += "|" + response + "|H";
                return $q.reject("I");
            }
        ).finally(
            function() { $scope.result += "|J"; }
        )
    }
]);
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="MyModule" ng-controller="MyCtrl">
  result: {{result}}
</div>

【问题讨论】:

    标签: angularjs angular-promise


    【解决方案1】:

    这是我看完@bmceldowney提供的link后得出的结论:

    流程总是会转到下一个then,所以为了停止,不要在需要停止的路径/promise上提供下一个then,而只把下一个then放在需要继续的路径/承诺。

    在我的情况下,我不希望链在收到第一个承诺的错误后继续,所以下一个 then 应该附加在 第二个承诺上,而不是第一个 @987654326 @:

    d0.promise.then(
        function(response) {
            // ...
            return d1.promise.then(     // append the next then here ...
                // ...
            ).catch (
                // ...
            ).finally(
                // ...
            );
        }
    ).catch (
        // ...
    ).finally(
        // ...
    );                                  // ... instead of here
    

    angular.module("MyModule", []).controller("MyCtrl", ["$scope", "$q", "$timeout",
        function($scope, $q, $timeout) {
            $scope.result = [];
    
            var d0 = $q.defer();
            $timeout(function() { d0.reject(); }, 1000);
            
            d0.promise.then(
                function(response) {
                    $scope.result.push("d0 successful");
    
                    var d1 = $q.defer();
                    $timeout(function() { d1.reject(); }, 1000);
                    
                    return d1.promise.then(
                        function(response) { $scope.result.push("d1 successful"); }
                    ).catch (
                        function(response) { $scope.result.push("d1 failed"); }
                    ).finally(
                        function() { $scope.result.push("finally2"); }
                    );
                }
            ).catch (
                function(response) { $scope.result.push("d0 failed"); }
            ).finally(
                function() { $scope.result.push("finally1"); }
            );
        }
    ]);
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
    <div ng-app="MyModule" ng-controller="MyCtrl">
      <p>result:</p>
      <div ng-repeat="msg in result">{{msg}}</div>
    </div>

    【讨论】:

      【解决方案2】:

      来自$q.rejectdocumentation

      当将 deferreds/promise 与熟悉的 try/catch/throw 行为进行比较时,将拒绝视为 JavaScript 中的 throw 关键字。这也意味着,如果您通过 promise 错误回调“捕获”错误,并且希望将错误转发到从当前 promise 派生的 promise,则必须通过返回通过拒绝构造的拒绝来“重新抛出”错误。 em>

      reject 不会自动中止 Promise 链,它只会继续下一个 Promise,为剩余的每个 Promise 调用错误处理程序。

      此外,无论链是否出错,finally 回调总是会运行。如果您不希望它运行,则由您手动检查 Promise 的状态。

      编辑:

      这里有一个答案链接,显示了如何链接错误:

      Break promise chain and call a function based on the step in the chain where it is broken (rejected)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-29
        • 1970-01-01
        • 2017-02-18
        • 2019-09-08
        • 2019-06-27
        • 1970-01-01
        • 2017-06-15
        • 1970-01-01
        相关资源
        最近更新 更多