web-dev-qa-db-de.com

Wann wird dann (Erfolg, Misserfolg) als Gegenmodell für Versprechen angesehen?

Ich habe mir das bluebird Versprechen FAQ angesehen, in dem erwähnt wird, dass .then(success, fail) ein Antipattern ist. Ich verstehe die Erklärung nicht so genau wie das Try and Catch. Was ist daran falsch?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

Es scheint, dass das Beispiel das Folgende als den richtigen Weg vorschlägt.

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

Was ist der Unterschied?

145
user2127480

Was ist der Unterschied?

Der Aufruf .then() gibt ein Versprechen zurück, das abgelehnt wird, falls der Rückruf einen Fehler auslöst. Das bedeutet, wenn Ihr Erfolg logger fehlschlägt, wird der Fehler an den folgenden .catch()-Callback weitergeleitet, jedoch nicht an den fail-Callback, der mit success zusammenarbeitet.

Hier ist ein control flow Diagramm:

control flow diagram of then with two argumentscontrol flow diagram of then catch chain

Um es in synchronem Code auszudrücken:

// some_promise_call().then(logger.log, logger.log)
then: {
    try {
        var results = some_call();
    } catch(e) {
        logger.log(e);
        break then;
    } // else
        logger.log(results);
}

Die zweite log (die dem ersten Argument von .then() ähnelt) wird nur ausgeführt, wenn keine Ausnahme aufgetreten ist. Der beschriftete Block und die break-Anweisung fühlen sich ein bisschen seltsam an, genau das hat python try-except-else für (empfohlenes Lesen!).

// some_promise_call().then(logger.log).catch(logger.log)
try {
    var results = some_call();
    logger.log(results);
} catch(e) {
    logger.log(e);
}

Der catch-Logger behandelt auch Ausnahmen vom Erfolgsprotokollaufruf.

Soviel zum Unterschied.

Ich verstehe die Erklärung nicht so genau wie das Try and Catch

Das Argument ist, dass Sie normalerweise Fehler in jedem Verarbeitungsschritt abfangen möchten und dass Sie es nicht in Ketten verwenden sollten. Die Erwartung ist, dass Sie nur einen abschließenden Handler haben, der alle Fehler behandelt. Wenn Sie jedoch das "Antipattern" verwenden, werden Fehler in einigen Then-Callbacks nicht behandelt.

Dieses Muster ist jedoch sehr nützlich: Wenn Sie Fehler behandeln möchten, die genau in diesem Schritt aufgetreten sind, und Sie möchten etwas ganz anderes tun, wenn kein Fehler aufgetreten ist, d. H. Wenn der Fehler nicht wiederherstellbar ist. Beachten Sie, dass dies Verzweigung Ihres Kontrollflusses ist. Das ist natürlich manchmal erwünscht.


Was ist daran falsch?

some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })

Dass Sie Ihren Rückruf wiederholen mussten. Du willst lieber

some_promise_call()
   .catch(function(e) {
       return e; // it's OK, we'll just log it
   })
   .done(function(res) {
       logger.log(res);
   });

Sie könnten auch erwägen, .finally() dafür zu verwenden.

172
Bergi

Die beiden sind nicht ganz identisch. Der Unterschied ist, dass das erste Beispiel keine Ausnahme feststellt, die in Ihrem success -Handler ausgelöst wird. Wenn Ihre Methode also immer nur gelöste Versprechen zurückgeben soll, wie dies häufig der Fall ist, benötigen Sie einen nachlaufenden catch -Handler (oder einen anderen then mit einem leeren success-Parameter). Sicher, es kann sein, dass Ihr then -Handler nichts tut, was möglicherweise fehlschlagen könnte. In diesem Fall könnte die Verwendung eines 2-Parameters then in Ordnung sein.

Ich glaube jedoch, dass der Sinn des Textes, mit dem Sie verlinkt haben, darin besteht, dass then hauptsächlich Callbacks nützlich ist, um eine Reihe asynchroner Schritte zu verketten und wenn Sie dies tatsächlich tun, die 2-Parameter-Form von then verhält sich aus dem oben genannten Grund nicht ganz so, wie erwartet. Es ist besonders nicht intuitiv, wenn es in der Mitte der Kette verwendet wird.

Als jemand, der viel komplizierte asynchrone Sachen gemacht hat und in Ecken wie diese gestoßen ist, mehr als ich zugeben möchte, empfehle ich wirklich, dieses Anti-Pattern zu vermeiden und auf den separaten Handler-Ansatz zu gehen.

30
acjay

Indem wir die Vor- und Nachteile beider betrachten, können wir eine kalkulierte Abschätzung machen, welche der Situation angemessen ist. Dies sind die zwei Hauptansätze zur Umsetzung von Versprechen. Beide haben Plus und Minus 

Fangansatz

some_promise_call()
.then(function(res) { logger.log(res) })
.catch(function(err) { logger.log(err) })

Vorteile

  1. Alle Fehler werden von einem Fangblock behandelt.
  2. Sogar eine Ausnahme im damaligen Block.
  3. Verkettung mehrerer Erfolgsrückrufe

Nachteile

  1. Bei Verkettungen wird es schwierig, unterschiedliche Fehlermeldungen anzuzeigen.

Erfolg/Fehleransatz

some_promise_call()
.then(function success(res) { logger.log(res) },
      function error(err) { logger.log(err) })

Vorteile

  1. Sie erhalten eine feinkörnige Fehlerkontrolle.
  2. Sie können eine allgemeine Fehlerbehandlungsfunktion für verschiedene Fehlerkategorien wie Db-Fehler, 500 Fehler usw. haben. 

Nachteile

  1. Sie benötigen noch eine andere catch, wenn Sie Fehler behandeln möchten, die vom Erfolgsrückruf ausgelöst werden
14
aWebDeveloper

Einfach erklären:

In ES2018

Wenn die catch-Methode mit dem Argument onRejected aufgerufen wird, wird die Folgende Schritte werden unternommen:

  1. Versprechen sei dieser Wert.
  2. Rückkehr ? Invoke (Versprechen, "dann", "undefined, onRejected").

das bedeutet:

promise.then(f1).catch(f2)

gleich

promise.then(f1).then(undefiend, f2)
0
saltfish

Mit .then().catch() können Sie Promise Chaining aktivieren, das zur Erfüllung eines Workflows erforderlich ist. Möglicherweise müssen Sie einige Informationen aus der Datenbank lesen, um sie an eine asynchrone API zu übergeben und anschließend die Antwort zu bearbeiten. Möglicherweise möchten Sie die Antwort zurück in die Datenbank übertragen. Die Handhabung all dieser Workflows mit Ihrem Konzept ist machbar, aber sehr schwierig zu verwalten. Die bessere Lösung ist then().then().then().then().catch(), die alle Fehler in nur einem Fang erhält und Sie die Wartbarkeit des Codes behalten lässt.

0
Jayant Varshney