[解決済み] 約束の連鎖を切断し、切断された連鎖のステップに応じた関数を呼び出す(拒否)
質問
更新しました。
この投稿を将来見る人のために、私は このデモは、plumaの回答 .
質問です。
私の目標はかなり簡単なようです。
step(1)
.then(function() {
return step(2);
}, function() {
stepError(1);
return $q.reject();
})
.then(function() {
}, function() {
stepError(2);
});
function step(n) {
var deferred = $q.defer();
//fail on step 1
(n === 1) ? deferred.reject() : deferred.resolve();
return deferred.promise;
}
function stepError(n) {
console.log(n);
}
ここで問題なのは、もしステップ1で失敗した場合、両方の
stepError(1)
と
stepError(2)
が発射されます。もし私が
return $q.reject
とすると
stepError(2)
は解雇されませんが
step(2)
は解雇されるでしょう、それは理解できます。自分がやろうとしていること以外はすべて達成した。
エラーチェーンのすべての関数を呼び出すことなく、拒絶時に関数を呼び出すことができるように、どのようにプロミスを書けばよいのでしょうか?あるいは、これを達成するための別の方法がありますか?
ライブデモはこちら をご覧ください。
更新しました。
I
種類
が解決しました。ここでは、チェーンの末尾でエラーをキャッチし、そのデータを
reject(data)
にデータを渡して、エラー関数でどのような問題を処理すべきかを知ることができるようにしています。私はデータに依存したくないので、これは実際には私の要件を満たしていません。ダサいですが、私の場合、返されたデータに依存して何をすべきかを決定するよりも、エラー コールバックを関数に渡す方がすっきりします。
step(1)
.then(function() {
return step(2);
})
.then(function() {
return step(3);
})
.then(false,
function(x) {
stepError(x);
}
);
function step(n) {
console.log('Step '+n);
var deferred = $q.defer();
(n === 1) ? deferred.reject(n) : deferred.resolve(n);
return deferred.promise;
}
function stepError(n) {
console.log('Error '+n);
}
どのように解決するのですか?
あなたのコードが期待通りに動かない理由は、あなたが考えていることとは異なることを実際に行っているからです。
次のようなものがあるとします。
stepOne()
.then(stepTwo, handleErrorOne)
.then(stepThree, handleErrorTwo)
.then(null, handleErrorThree);
何が起こっているかをよりよく理解するために、これが同期コードであると仮定して
try
/
catch
のブロックがあります。
try {
try {
try {
var a = stepOne();
} catch(e1) {
a = handleErrorOne(e1);
}
var b = stepTwo(a);
} catch(e2) {
b = handleErrorTwo(e2);
}
var c = stepThree(b);
} catch(e3) {
c = handleErrorThree(e3);
}
は
onRejected
ハンドラ(の第二引数
then
のような) エラー修正メカニズムです。
catch
ブロックのようなもの)です。でエラーが発生した場合
handleErrorOne
でエラーが発生した場合、次の catch ブロックで捕捉されます (
catch(e2)
) によって捕捉され、以下同様です。
これは明らかにあなたの意図したものではありません。
何が間違っていても、解決チェーン全体が失敗するようにしたいとしましょう。
stepOne()
.then(function(a) {
return stepTwo(a).then(null, handleErrorTwo);
}, handleErrorOne)
.then(function(b) {
return stepThree(b).then(null, handleErrorThree);
});
注
handleErrorOne
の場合のみ呼び出されるからです。
stepOne
が拒否した場合のみ呼び出されるからです (これはチェーンの最初の関数なので、この時点でチェーンが拒否された場合、その関数の約束のせいでしかありえないことが分かっています)。
重要な変更は、他の関数のエラーハンドラがメインの約束の連鎖の一部ではないことです。その代わりに、各ステップは独自の
onRejected
があり、ステップが拒否された場合のみ呼び出されます(ただし、メインチェーンから直接到達することはできません)。
これがうまくいく理由は、両方の
onFulfilled
と
onRejected
はオプションの引数で
then
メソッドに渡すオプションの引数です。もし、約束が果たされ(つまり、解決され)、次の
then
が存在しない場合、その連鎖の中で
onFulfilled
ハンドラを持たない場合、そのようなハンドラを持つものが現れるまでチェーンは継続されます。
これは以下の2行が等価であることを意味します。
stepOne().then(stepTwo, handleErrorOne)
stepOne().then(null, handleErrorOne).then(stepTwo)
しかし、次の行は ではなく は上の二つと同等です。
stepOne().then(stepTwo).then(null, handleErrorOne)
Angularのpromiseライブラリ
$q
は kriskowal の
Q
ライブラリ (これはよりリッチな API を持ちます。
$q
). Qの
API ドキュメント
を参照してください。Qは
Promises/A+仕様
を実装しており、どのように
then
とプロミスの解決動作が正確にどのように動作するかについて詳しく説明されています。
をEDITしました。
また、エラーハンドラでチェーンから抜け出したい場合は、rejected promiseを返すか、Errorを投げる必要があることも覚えておいてください(これは自動的にrejected promiseに捕捉・ラップされます)。もし、プロミスを返さないのであれば
then
は戻り値をresolveプロミスにラップしてくれます。
これは、何も返さない場合、事実上、解決されたプロミスを値として返していることを意味します。
undefined
.
関連
-
親子コンポーネント通信を解決する3つのVueスロット
-
Vueがechartsのtooltipにクリックイベントを追加するケーススタディ
-
元のイベントが実行されなかった後に要素を追加するためのjQueryソリューション
-
vueの補間表現とv-textディレクティブの違いについて
-
[解決済み] テスト
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み】React Nativeアプリをターミナルから実行するとエラーが発生する(iOS)
-
[解決済み] TypeError: 未定義のプロパティ 'then' を読み取ることができません。
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] 明示的なプロミス構築のアンチパターンとそれを回避する方法とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JSクロスドメインソリューション リアクト構成 リバースプロキシ
-
vueはopenlayersを使用してスカイマップとガオードマップをロードする
-
vue+webrtc(Tencent cloud)ライブ機能の実践を実現するために
-
[解決済み】gulp anythingを実行するたびに、アサーションエラーが発生します。- タスク関数を指定する必要があります
-
[解決済み] TypeError: $.ajax(...) is not a function?
-
[解決済み】JavaScriptエラー(Uncaught SyntaxError: Unexpected end of input)
-
[解決済み】 Uncaught TypeError : undefined のプロパティ 'replace' を読み取れない In Grid
-
nodejs unhandledPromiseRejectionWarning メッセージ
-
JavaScriptのgetElementById、getElementsByTagNam、getElementsByClassNameの違いと使い方
-
jq は html ページとデータを動的に分割する。