Angular Promises - 从成功跳转到失败回调?

Angular Promises - Jumping from the success to the failure callback?

我觉得我可能正在做一些 Promises 不打算做的事情,但我们开始吧,这就是我想做的:

$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
        if ( response.data.isAllGood ) {
            $scope.myData = response.data;
        }
        else {
            // TODO HERE! Call the failure function!
        }
    },
    function failure() {
        $http.get('/api/endpoint/PlanB.json').then(
            function planBsuccess( response ) {
                $scope.myData = response.data;
            }
        );
    }
).then(function doOtherStuff() {});

如果 PlanA 端点 returns 是 404 或 500...,这将按预期工作,但如果它成功,但有错误数据(例如,isAllGood 是false),那么我希望它能到达失败回调。有没有简单的方法来做到这一点?

我试过调用 $q.defer().reject 并返回那个承诺,但是这只是调用 doOtherStuff 的失败回调。

不要这样做。它的糟糕设计。这是一个更简单的解决方案:

$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
        if ( response.data.isAllGood ) {
            $scope.myData = response.data;
        }
        else {
             foo();
        }
    },
    function failure() {
        foo();
    }
).then(function doOtherStuff() {});

foo = function(){
  $http.get('/api/endpoint/PlanB.json').then(
        function planBsuccess( response ) {
            $scope.myData = response.data;
        }
   );
};

话虽如此,我认为即使这样也是在滥用 $http 的设计方式。相反,我会做类似

的事情
$http.get('/api/endpoint/PlanA.json').then(
    function success( response ) {
      $scope.myData = response.data;
    },
    function failure() {
        trueFailureFunc();
    }
).then(validateData());

validateData = function(){
    if ( response.data.isAllGood ) {
      $scope.myData = response.data;
    }
     else {
        getDataFromOtherSource();
    }
}

是的,有一种简单的方法可以做到。您只需将失败回调 链接到成功回调 之后,而不是紧挨着它 - 请参阅 When is .then(success, fail) considered an antipattern for promises? 以获得更详细的解释。

$http.get('/api/endpoint/PlanA.json').then(function success(response) {
    if (response.data.isAllGood) {
        $scope.myData = response.data;
    } else {
        return $q.reject(); // fail this promise
    }
}).catch(function failure() { // and handle it here (also errors originating from $http)
    return $http.get('/api/endpoint/PlanB.json').then(function planBsuccess(response) {
//  ^^^^^^ don't forget to wait with doOtherStuff for plan B
        $scope.myData = response.data;
    });
}).then(function doOtherStuff() {});

甚至更好,避免了 $scope 赋值的代码重复:

$http.get('/api/endpoint/PlanA.json').then(function validate(response) {
    if (response.data.isAllGood)
        return response;
    else
        throw new Error("noGoodData");
}).catch(function failure() {
    return $http.get('/api/endpoint/PlanB.json');
}).then(function success(response) {
    $scope.myData = response.data;
    return doOtherStuff();
});