.catch
ネストされたプロミスに BEFORE と AFTERを置くことの違いが理解できません。
代替案1:
test1Async(10).then((res) => {
return test2Async(22)
.then((res) => {
return test3Async(100);
}).catch((err) => {
throw "ERROR AFTER THEN";
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
代替案2:
test1Async(10).then((res) => {
return test2Async(22)
.catch((err) => {
throw "ERROR BEFORE THEN";
})
.then((res) => {
return test3Async(100);
});
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});
各関数の動作は次のとおりです。数値が の場合、test1 は失敗し、数値が の<0
場合、test2 は失敗し> 10
、数値が でない場合、test3 は失敗します100
。この場合、test2 のみが失敗します。
test2Async を実行して失敗させようとしましたが、BEFORE と AFTER の両方で同じように動作し、test3Async は実行されません。catch を異なる場所に配置することの主な違いを説明していただけますか?
各関数で、console.log('Running test X')
それが実行されるかどうかを確認します。
この質問は私が以前投稿したスレッドから生じていますネストされたコールバックを Promise に変換するにはどうすればよいでしょうか?これは別の問題なので、別のトピックを投稿する価値があると思います。
ベストアンサー1
つまり、基本的には、これら 2 つの違いは何か (p
以前のコードから作成された Promise はどこか) を尋ねていることになります。
return p.then(...).catch(...);
そして
return p.catch(...).then(...);
.then()
p が解決されるか拒否されるかによって違いがありますが、それらの違いが重要かどうかは、またはハンドラー内のコードが何を.catch()
行うかによって決まります。
解決すると何が起こるかp
:
最初のスキームでは、p
が解決されると、.then()
ハンドラーが呼び出されます。その.then()
ハンドラーが値を返すか、最終的に解決される別の promiseを返す.catch()
場合、ハンドラーはスキップされます。ただし、ハンドラーが.then()
最終的に拒否される promise をスローするか返す場合、ハンドラーは元の promise の拒否だけでなく、ハンドラーで発生するエラー.catch()
に対しても実行されます。p
.then()
2 番目のスキームでは、p
解決時に.then()
ハンドラーが呼び出されます。その.then()
ハンドラーが、最終的に拒否される Promise をスローまたは返す場合、.catch()
ハンドラーはチェーン内でその前にあるため、それをキャッチできません。
これが違い #1 です。.catch()
ハンドラーが AFTER の場合、ハンドラー内でエラーをキャッチすることもできます.then()
。
拒否された場合はどうなるかp
:
さて、最初のスキームでは、Promise がp
拒否された場合、.then()
ハンドラーはスキップされ、.catch()
期待どおりにハンドラーが呼び出されます。.catch()
ハンドラーで何を行うかによって、最終結果として何が返されるかが決まります。ハンドラーから値を返すだけの場合.catch()
、または最終的に解決される Promise を返す場合は、エラーを「処理」して通常どおりに返したため、Promise チェーンは解決済みの状態に切り替わります。ハンドラーで拒否された Promise をスローまたは返す場合は、.catch()
返された Promise は拒否されたままになります。
2 番目のスキームでは、Promise がp
拒否された場合、.catch()
ハンドラーが呼び出されます。.catch()
ハンドラーから通常の値または最終的に解決される Promise を返すと (つまり、エラーを「処理」すると)、Promise チェーンは解決済みの状態に切り替わり、.then()
その後のハンドラーが.catch()
呼び出されます。
これが違い #2 です。.catch()
ハンドラーが BEFORE の場合、エラーを処理してハンドラー.then()
が呼び出されるようにすることができます。
which を使用する場合:
元のプロミスまたはハンドラーの.catch()
いずれかでエラーをキャッチできる 1 つのハンドラーのみが必要で、拒否によってそのハンドラーがスキップされる場合は、最初のスキームを使用します。p
.then()
p
.then()
元のプロミスのエラーをキャッチしp
、場合によっては (条件に応じて) プロミス チェーンを解決済みとして続行してハンドラーを実行できるようにする場合は、2 番目のスキームを使用します.then()
。
もう一つの選択肢
次のように渡すことができる両方のコールバックを使用する別のオプションが 1 つあります.then()
。
p.then(fn1, fn2)
これにより、fn1
またはのいずれか 1 つだけfn2
が呼び出されることが保証されます。 がp
解決された場合はfn1
が呼び出されます。 がp
拒否された場合は がfn2
呼び出されます。 の結果が変更されても が呼び出されるfn1
ことはありませんfn2
し、その逆も同様です。したがって、ハンドラー自体で何が起こっても 2 つのハンドラーのうち 1 つだけが呼び出されることを確実にしたい場合は、 を使用できますp.then(fn1, fn2)
。