$ 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>
Ответы
Ответ 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.