Ich habe Probleme, den Unterschied zwischen Putten zu verstehen .catch
VOR und NACH einem verschachtelten Versprechen .
Alternative 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);
});
Alternative 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);
});
Das Verhalten jeder Funktion ist wie folgt: Test1 <0
schlägt fehl, wenn Nummer ist. > 10
Test2 schlägt fehl, wenn Nummer ist, und Test3 schlägt fehl, wenn Nummer nicht ist 100
. In diesem Fall schlägt test2 nur fehl.
Ich habe versucht, test2Async auszuführen und zum Fehlschlagen zu bringen. BEFORE und AFTER verhalten sich dann gleich und führen test3Async nicht aus. Kann mir jemand den Hauptunterschied für das Platzieren von Fängen an verschiedenen Orten erklären?
In jeder Funktion I, console.log('Running test X')
um zu überprüfen, ob es ausgeführt wird.
Diese Frage stellt sich aufgrund des vorherigen Threads, den ich gepostet habe. Wie kann man einen verschachtelten Rückruf in ein Versprechen verwandeln? . Ich denke, es ist ein anderes Problem und es lohnt sich, ein anderes Thema zu veröffentlichen.
quelle
Antworten:
Im Grunde fragen Sie sich also, was der Unterschied zwischen diesen beiden ist (wo
p
ist ein Versprechen, das aus einem vorherigen Code erstellt wurde):und
Es gibt Unterschiede, entweder wenn p aufgelöst oder abgelehnt wird, aber ob diese Unterschiede wichtig sind oder nicht, hängt davon ab, was der Code in den
.then()
oder.catch()
Handlern tut.Was passiert, wenn
p
gelöst wird:Im ersten Schema wird beim
p
Auflösen der.then()
Handler aufgerufen. Wenn dieser.then()
Handler entweder einen Wert oder ein anderes Versprechen zurückgibt, das schließlich aufgelöst wird, wird der.catch()
Handler übersprungen. Wenn der.then()
Handler jedoch ein Versprechen auslöst oder zurückgibt, das schließlich.catch()
abgelehnt wird, führt der Handler sowohl eine Ablehnung im ursprünglichen Versprechenp
als auch einen Fehler aus, der im.then()
Handler auftritt .Im zweiten Schema wird beim
p
Auflösen der.then()
Handler aufgerufen. Wenn dieser.then()
Handler ein Versprechen wirft oder zurückgibt, das schließlich abgelehnt wird, kann der.catch()
Handler das nicht abfangen, da es sich in der Kette davor befindet.Das ist also der Unterschied Nr. 1. Wenn der
.catch()
Handler AFTER ist, kann er auch Fehler im.then()
Handler abfangen .Was passiert, wenn
p
abgelehnt wird:Wenn das Versprechen im ersten Schema
p
abgelehnt wird, wird der.then()
Handler übersprungen und der.catch()
Handler wird wie erwartet aufgerufen. Was Sie im.catch()
Handler tun, bestimmt, was als Endergebnis zurückgegeben wird. Wenn Sie nur einen Wert vom.catch()
Handler zurückgeben oder ein Versprechen zurückgeben, das schließlich aufgelöst wird, wechselt die Versprechen-Kette in den gelösten Zustand, weil Sie den Fehler "behandelt" und normal zurückgegeben haben. Wenn Sie ein abgelehntes Versprechen in den.catch()
Handler werfen oder zurückgeben, bleibt das zurückgegebene Versprechen abgelehnt.Wenn im zweiten Schema das Versprechen
p
abgelehnt wird, wird der.catch()
Handler aufgerufen. Wenn Sie einen normalen Wert oder ein Versprechen zurückgeben, das schließlich vom.catch()
Handler behoben wird (wodurch der Fehler "behandelt" wird), wechselt die Versprechen-Kette in den aufgelösten Zustand und der.then()
Handler nach dem.catch()
Aufruf des.Das ist also der Unterschied Nr. 2. Wenn der
.catch()
Handler VORHER ist, kann er den Fehler behandeln und dem.then()
Handler ermöglichen, weiterhin aufgerufen zu werden.Wann welche zu verwenden:
Verwenden Sie das erste Schema, wenn Sie nur einen
.catch()
Handler möchten , der Fehler entweder im ursprünglichen Versprechenp
oder im.then()
Handler abfangen kann, und eine Ablehnung vonp
sollte den.then()
Handler überspringen .Verwenden Sie das zweite Schema, wenn Sie in der Lage sein möchten, Fehler im ursprünglichen Versprechen zu erkennen,
p
und möglicherweise (abhängig von den Bedingungen) zulassen, dass die Versprechen-Kette wie gelöst fortgesetzt wird, und so den.then()
Handler ausführen .Die andere Option
Es gibt eine weitere Option, um beide Rückrufe zu verwenden, an die Sie
.then()
wie folgt übergeben können :Dies garantiert, dass nur einer von
fn1
oderfn2
jemals aufgerufen wird. Wenn es aufgelöst wirdp
,fn1
wird es aufgerufen. Wennp
abgelehnt,fn2
wird aufgerufen. Keine Änderung des Ergebnisses infn1
kann jemals dazu führen, dassfn2
man angerufen wird oder umgekehrt. Wenn Sie also unbedingt sicherstellen möchten, dass nur einer Ihrer beiden Handler aufgerufen wird, unabhängig davon, was in den Handlern selbst geschieht, können Sie verwendenp.then(fn1, fn2)
.quelle
.then()
und.catch()
, die Sie beantworten. Darüber hinaus geben Sie einige Tipps, wann Sie welche Reihenfolge verwenden sollen. Ich halte es für angebracht, eine dritte Option zu erwähnen, nämlich die Übergabe des Erfolgs- und des Fehlerbehandlungsprogramms an .then () . In diesem Fall wird höchstens ein Handler aufgerufen.Promise.reject(new Error("F")).then(x => x).catch(e => {console.log(e); return [1]}).then(console.log)
undPromise.resolve([2]).then(x => x).catch(e => [1]).then(console.log)
.then(this.setState({isModalOpen: false}))
. Sie übergeben keinen Funktionsverweis auf,.then()
sodass der Code in den Parens sofort ausgeführt wird (bevor das Versprechen aufgelöst wird). Es sollte sein.then(() => this.setState({isModalOpen: false}))
.Die Antwort von jfriend00 ist ausgezeichnet, aber ich dachte, es wäre eine gute Idee, den analogen synchronen Code hinzuzufügen.
ähnelt dem synchronen:
Wenn
iMightThrow()
nicht werfen,then()
wird gerufen. Wenn es wirft (oder wenn esthen()
selbst wirft),handleCatch()
wird es aufgerufen. Beachten Sie, dass dercatch
Block keine Kontrolle darüber hat, ob erthen
aufgerufen wird oder nicht .Andererseits,
ähnelt dem synchronen:
In diesem Fall wird ausgeführt, wenn
iMightThrow()
nicht geworfenthen()
wird. Wenn es auslöst, muss entschieden werdenhandleCatch()
, obthen()
aufgerufen wird, denn wenn erneuthandleCatch()
geworfen wird,then()
wird es nicht aufgerufen, da die Ausnahme sofort an den Anrufer geworfen wird. WennhandleCatch()
das Problem ordnungsgemäß behandelt werden kann,then()
wird es aufgerufen.quelle
then()
in afinally{...}
then()
infinally{...}
, wäre es nicht falsch , auch genannt werden , wennhandleCatch()
wirft? Denken Sie daran, dass mein Ziel darin bestand, analogen synchronen Code