2015-04-28 2 views
2

Я чувствую, что я могу делать то, что обещания не были разработаны, чтобы сделать, но здесь мы идем, это то, что я хотел бы сделать:Угловые обещания - прыжки с успеха на обратный вызов отказа?

$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 Конечная точка возвращает 404 или 500 ... но если она преуспевает, но имеет плохие данные (например, isAllGood - это ложь), то мне бы хотелось, чтобы она попала в обратный вызов сбоя. Есть простой способ сделать это?

Я пробовал звонить $q.defer().reject и возвращать это обещание, однако это просто вызывает обратный вызов отказа для doOtherStuff.

ответ

0

Не делайте этого. Плохой дизайн. Здесь гораздо более простое решение:

$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(); 
    } 
} 
+0

Почему downvote? –

+0

Спасибо за это. Я в основном завернул ваш второй в функции, которая вернула себе обещание, и когда он «разрешил», я вызвал 'doOtherStuff'. Благодаря! –

1

Да, есть простой способ сделать это. Вам просто нужно связать обратный вызов отказа после успешный обратный вызов, а не рядом с ним - см. 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(); 
}); 
Смежные вопросы