Fangplatzierung VORHER und NACHHER

Lesezeit: 8 Minuten

Benutzer-Avatar
Zanko

Ich habe Schwierigkeiten, den Unterschied zwischen Putten zu verstehen .catch BEFORE und AFTER dann in einem verschachtelten Promise.

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 schlägt fehl, wenn Zahl ist <0 test2 schlägt fehl, wenn Zahl ist > 10 und test3 schlägt fehl, wenn Zahl nicht ist 100. In diesem Fall schlägt nur test2 fehl.

Ich habe versucht, test2Async auszuführen und zum Scheitern zu bringen, sowohl BEFORE als auch AFTER verhalten sich dann gleich und das führt nicht zu test3Async. Kann mir jemand den Hauptunterschied für das Platzieren von Fang an verschiedenen Orten erklären?

In jeder Funktion I console.log('Running test X') um zu prüfen, ob es ausgeführt wird.

Diese Frage stellt sich aufgrund des vorherigen Threads, den ich gepostet habe. How to turn nested callback into Promise?. Ich denke, es ist ein anderes Problem und es lohnt sich, ein anderes Thema zu posten.

  • Sowohl .then als auch .catch können das Versprechen ändern … also bin ich mir nicht sicher, woher das Missverständnis kommt. Wenn Sie catch vor das .then setzen, werden Ablehnungen abgefangen, die vor dem .then aufgetreten sind, und das .then führt seine Done/Fail-Callbacks basierend auf dem aus, was innerhalb des .catch passiert, und umgekehrt, wenn Sie sie austauschen.

    – Kevin B

    2. Februar 2017 um 22:02 Uhr


  • Entschuldigung, wenn meine Frage nicht klar war. Aber wie gesagt, in diesem Fall verhalten sich beide Fälle gleich, sodass ich den Unterschied nicht erkennen kann. Können Sie mir sagen, wann wir catch VORHER und wann wir uns entschieden haben, es NACHHER zu setzen? es danach zu setzen, scheint wirklich intuitiv und üblich zu sein. Ich bin mir nur nicht sicher, warum wir es manchmal davor setzen

    – Zanko

    2. Februar 2017 um 22:05 Uhr

  • Wenn sie die gleiche Leistung erbringen, liegt das einfach daran, dass das, was jeder tut, das Ergebnis in diesem speziellen Fall nicht verändert. Eine geringfügige Änderung an einem der beiden könnte das Ergebnis verändern.

    – Kevin B

    2. Februar 2017 um 22:06 Uhr


  • Was meinst du mit “Ändern des Ergebnisses”. Entschuldigung, ich bin wirklich verwirrt, haha

    – Zanko

    2. Februar 2017 um 22:15 Uhr

  • Wenn Sie zum Beispiel, anstatt einen Fehler zu werfen, einfach nichts getan haben, würde das Versprechen von „Abgelehnt“ zu „Aufgelöst“ wechseln. Das würde natürlich das Ergebnis verändern, denn das Versprechen ist jetzt ein eingelöstes Versprechen und kein zurückgewiesenes. (es sei denn natürlich, es wurde bereits gelöst, in diesem Fall wäre der Fang sowieso nicht gelaufen)

    – Kevin B

    2. Februar 2017 um 22:20 Uhr


Benutzer-Avatar
jfriend00

Im Grunde fragen Sie also, was der Unterschied zwischen diesen beiden ist (wo p ist ein Versprechen, das aus einem früheren Code erstellt wurde):

return p.then(...).catch(...);

und

return p.catch(...).then(...);

Es gibt Unterschiede, wenn p auflöst oder ablehnt, aber ob diese Unterschiede eine Rolle spielen oder nicht, hängt davon ab, was der Code in enthält .then() oder .catch() Handler tut.

Was passiert, wenn p löst:

Im ersten Schema, wann p beschließt, die .then() Handler wird gerufen. Wenn das .then() -Handler gibt entweder einen Wert oder ein anderes Promise zurück, das schließlich aufgelöst wird, und dann die .catch() Handler wird übersprungen. Aber wenn die .then() Der Handler löst entweder ein Promise aus oder gibt es zurück, das schließlich abgelehnt wird .catch() Der Handler führt für beide eine Ablehnung im ursprünglichen Promise aus psondern auch ein Fehler, der in der auftritt .then() Handler.

Im zweiten Schema, wann p beschließt, die .then() Handler wird gerufen. Wenn das .then() Der Handler löst entweder ein Promise aus oder gibt es zurück, das schließlich abgelehnt wird .catch() Der Handler kann das nicht abfangen, weil es in der Kette davor steht.

Das ist also der Unterschied Nr. 1. Wenn die .catch() handler AFTER ist, dann kann er auch Fehler innerhalb der abfangen .then() Handler.

Was passiert, wenn p lehnt ab:

Nun, im ersten Schema, wenn das Versprechen p ablehnt, dann die .then() Handler wird übersprungen und die .catch() handler wird aufgerufen, wie Sie es erwarten würden. Was machst du in der .catch() Der Handler bestimmt, was als Endergebnis zurückgegeben wird. Wenn Sie nur einen Wert aus der zurückgeben .catch() Handler ausführen oder ein Promise zurückgeben, das schließlich aufgelöst wird, dann wechselt die Promise-Kette in den gelösten Zustand, weil Sie den Fehler “behandelt” haben und normal zurückgekehrt sind. Wenn Sie ein abgelehntes Versprechen in die werfen oder zurückgeben .catch() Handler, dann bleibt das zurückgegebene Versprechen abgelehnt.

Im zweiten Schema, wenn das Versprechen p ablehnt, dann die .catch() Handler wird gerufen. Wenn Sie einen normalen Wert oder ein Versprechen zurückgeben, löst sich das schließlich aus der .catch() handler (also den Fehler “behandeln”), dann wechselt die Promise-Kette in den aufgelösten Zustand und die .then() Handler nach dem .catch() wird angerufen werden.

Das ist also der Unterschied Nr. 2. Wenn die .catch() handler VOR ist, dann kann er den Fehler behandeln und das zulassen .then() Handler noch angerufen werden.

Wann welche verwenden:

Verwenden Sie das erste Schema, wenn Sie nur eines möchten .catch() Handler, der Fehler im ursprünglichen Promise abfangen kann p oder im .then() Handler und eine Ablehnung von p sollte das überspringen .then() Handler.

Verwenden Sie das zweite Schema, wenn Sie Fehler im ursprünglichen Promise abfangen möchten p und vielleicht (abhängig von den Bedingungen) der Promise-Kette erlauben, wie aufgelöst fortzufahren, wodurch die ausgeführt wird .then() Handler.

Die andere Option

Es gibt eine weitere Option, um beide Rückrufe zu verwenden, an die Sie übergeben können .then() wie in:

 p.then(fn1, fn2)

Dies garantiert, dass nur einer von fn1 oder fn2 wird jemals angerufen. Wenn p löst sich dann auf fn1 wird angerufen werden. Wenn p lehnt dann ab fn2 wird angerufen werden. Keine Ergebnisänderung in fn1 jemals machen kann fn2 angerufen werden oder umgekehrt. Wenn Sie also absolut sicherstellen möchten, dass nur einer Ihrer beiden Handler aufgerufen wird, unabhängig davon, was in den Handlern selbst passiert, können Sie verwenden p.then(fn1, fn2).

  • Die Frage bezieht sich speziell auf die Reihenfolge von .then() und .catch(), was du antwortest. Außerdem geben Sie einige Tipps, wann Sie welche Reihenfolge verwenden sollten, wobei ich es für angebracht halte, eine dritte Option zu erwähnen, nämlich die Übergabe sowohl des Erfolgs- als auch des Fehlerhandlers an .dann(). In diesem Fall wird höchstens ein Handler aufgerufen.

    – Arne Hugo

    29. November 2017 um 11:10 Uhr


  • @ArneHugo – Guter Vorschlag. Ich fügte hinzu.

    – jfriend00

    29. November 2017 um 20:32 Uhr

  • Können wir also während des Promise Chaining .then .catch .catch .then Szenarien schreiben?

    – Kapil Raghuwanshi

    22. August 2019 um 7:45 Uhr


  • @KapilRaghuwanshi, ja, Sie können damit im Fehlerfall einen Standardwert übergeben. dh Promise.reject(new Error("F")).then(x => x).catch(e => {console.log(e); return [1]}).then(console.log) und Promise.resolve([2]).then(x => x).catch(e => [1]).then(console.log)

    – CervEd

    24. März 2020 um 15:01 Uhr


  • @DmitryShvedov – Wie ich vermutet habe, ist das falsch .then(this.setState({isModalOpen: false})). Sie übergeben keinen Funktionsverweis an .then() sodass der Code in den Klammern sofort ausgeführt wird (bevor das Promise aufgelöst wird). Es sollte sein .then(() => this.setState({isModalOpen: false})).

    – jfriend00

    23. Juli 2020 um 0:09 Uhr


Die Antwort von jfriend00 ist ausgezeichnet, aber ich dachte, es wäre eine gute Idee, den analogen synchronen Code hinzuzufügen.

return p.then(...).catch(...);

ist ähnlich dem synchronen:

try {
  iMightThrow() // like `p`
  then()
} catch (err) {
  handleCatch()
}

Wenn iMightThrow() wirft nicht, then() wird angerufen werden. Wenn es wirft (oder wenn then() selbst wirft), dann handleCatch() wird angerufen werden. Beachten Sie, wie die catch Block hat keine Kontrolle darüber, ob oder nicht then wird genannt.

Auf der anderen Seite,

return p.catch(...).then(...);

ist ähnlich dem synchronen:

try {
  iMightThrow()
} catch (err) {
  handleCatch()
}

then()

In diesem Fall, wenn iMightThrow() wirft dann nicht then() wird ausführen. Wenn es wirft, dann wäre es bis zu handleCatch() zu entscheiden, ob then() heißt, denn wenn handleCatch() wirft dann zurück then() wird nicht aufgerufen, da die Ausnahme sofort an den Aufrufer geworfen wird. Wenn handleCatch() kann das Problem dann anmutig behandeln then() wird angerufen werden.

  • Das ist eine gute Erklärung, aber Sie könnten das Waisenkind einwickeln then() in einem finally{...}

    – trk

    20. September 2018 um 5:25 Uhr

  • @82Tuskers, bist du sicher? Wenn ich setze then() in finally{...}würde es nicht fälschlicherweise auch wenn genannt werden handleCatch() wirft? Denken Sie daran, dass mein Ziel darin bestand, analogen synchronen Code zu zeigen, und nicht, verschiedene Möglichkeiten zur Behandlung von Ausnahmen vorzuschlagen

    – Akivajgordon

    20. September 2018 um 16:19 Uhr

  • Wenn wir also alle Fälle behandeln wollen, aber immer noch .then() verketten möchten, wäre es am besten, .then(do something).catch(log err and update state).then(do other thing).catch(log err) zu verwenden. wo wir versuchen, an jedem Punkt zu fangen, aber auch weiterhin die Stmnts auszuführen?

    – Anna

    27. Februar 2020 um 20:41 Uhr

1018270cookie-checkFangplatzierung VORHER und NACHHER

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy