次のコードスニペット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>
エラーは、エラーコールバックで$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"); });
});
成功/失敗をトライ/キャッチと考える
_try{
var val = dummyPromise();
} catch (e){
val = "SomeValue";
}
_
catchが例外をスローしない場合、エラーが処理されたと見なされるため、外部呼び出し関数は内部関数で発生したエラーを認識しません。
ここでも同様のことが起こります。チェーンの次のプロミスが失敗するためには、プロミスからreturn $q.reject();
を返す必要があります。 plunkerの例を参照してください: http://plnkr.co/edit/porOG8qVg2GkeddzVHu3?p=preview
理由は次のとおりです。エラーハンドラーがエラーを訂正するアクションを実行する場合があります。エラー関数では、エラーに対処する場合、特に指定がない限り、解決された新しいプロミスを返します。したがって、デフォルトで次のプロミスが失敗するのは妥当ではありません(try-catchのアナロジー)。
ちなみに、successハンドラからでも、エラー状態を感知して$q.reject()
を返すと、次の約束が得られますチェーンの失敗。エラーをキャッチして処理しているので、成功ハンドラに到達します。拒否したい場合は、$ q.reject();を返すことで拒否する必要があります。
コメントを要約して、promiseチェーンでエラーを伝播するには、次のいずれかを行います。
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)errorCallback
から$q.reject()
を返します。
_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 documentation から:
_This api should be used to forward rejection in a chain of promises.
_