Подтвердить что ты не робот

$ q обезопасить цепи обратного вызова

В следующем фрагменте кода error 1 и success 2 будет зарегистрирован. Как я могу распространять вызываемые обратные вызовы ошибок, а не вызываемые обратные вызовы успеха, если отложенный исходный текст отклонен.

angular.module("Foo", []);
angular
.module("Foo")
.controller("Bar", function ($q) {
    var deferred = $q.defer();
      deferred.reject();

      deferred.promise
          .then(
              /*success*/function () { console.log("success 1"); },
              /*error*/function () { console.log("error 1"); })
          .then(
              /*success*/function () { console.log("success 2"); },
              /*error*/function () { console.log("error 2"); });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Foo">
    <div ng-controller="Bar"></div>
</div>
4b9b3361

Ответ 1

Ошибка распространяется, возвращая $q.reject в обратном вызове ошибки

    var deferred = $q.defer();
      deferred.reject();

      deferred.promise
          .then(
              /*success*/function () { console.log("success 1"); },
              /*error*/function () { console.log("error 1"); return $q.reject('error 1')})
          .then(
              /*success*/function () { console.log("success 2"); },
              /*error*/function () { console.log("error 2"); });
});

Ответ 2

думать об успехе/неудаче как try/catch

try{
    var val = dummyPromise();
} catch (e){
    val = "SomeValue";
}

Если catch не генерирует исключение, считается, что ошибка обрабатывается, и, следовательно, внешняя функция вызова не видит ошибку, которая произошла во внутренней функции.

Подобные вещи, происходящие здесь, вы должны вернуть return $q.reject(); из обещания, чтобы следующее обещание в цепочке тоже потерпело неудачу. См. Пример plunker: http://plnkr.co/edit/porOG8qVg2GkeddzVHu3?p=preview

Причина: ваш обработчик ошибок может предпринять меры для исправления ошибки. В вашей функции ошибок вы имеете дело с ошибкой, если не указано иначе, она вернет новое обещание, которое будет разрешено. Поэтому нецелесообразно, чтобы по умолчанию было выполнено следующее обещание (аналогия с попытками).

Кстати, вы можете вернуть $q.reject() даже из обработчика успеха, если вы чувствуете ошибку, чтобы иметь следующее обещание в цепочке. Вы поймаете ошибку и обработаете ее - так что она попадает в обработчик успеха. Если вы хотите отклонить его, вы должны сделать это, возвращая $q.reject();

Ответ 3

Чтобы суммировать комментарии вверх, для распространения ошибок в цепочке обещаний:

1) Не указывайте errorCallback для then:

deferred.promise
.then(
  /*success*/function () { console.log("success 1"); },
.then(
  /*success*/function () { console.log("success 2"); },
  /*error*/function () { console.log("error 2"); }); // gets called

или

2) Верните $q.reject() из errorCallback:

deferred.promise
.then(
  /*success*/function () { console.log("success 1"); },
  /*error*/function (err) { console.log("error 1"); return $q.reject(err); });
.then(
  /*success*/function () { console.log("success 2"); },
  /*error*/function () { console.log("error 2"); }); // gets called

Из angular $q.reject документации:

This api should be used to forward rejection in a chain of promises.