Ich habe mir die FAQ zu Bluebird-Versprechungen angesehen , in der erwähnt wird, dass .then(success, fail)
es sich um ein Antimuster handelt . Ich verstehe die Erklärung für das Versuchen und Fangen nicht ganz. Was ist daran folgendes falsch?
some_promise_call()
.then(function(res) { logger.log(res) }, function(err) { logger.log(err) })
Es scheint, dass das Beispiel Folgendes 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?
javascript
node.js
promise
bluebird
user2127480
quelle
quelle
then().catch()
ist besser lesbar, da Sie nicht nach Komma suchen und untersuchen müssen, ob dieser Rückruf erfolgreich ist oder fehlschlägt..catch
, wissen Sie nicht, welcher Schritt das Problem verursacht hat - innerhalb des letztenthen
oder irgendwo anders in der Versprechenskette. Es hat also seinen eigenen Nachteil.some_promise_call() .then(function fulfilled(res) { logger.log(res) }, function rejected(err) { logger.log(err) })
Antworten:
Der
.then()
Anruf gibt ein Versprechen zurück, das abgelehnt wird, falls der Rückruf einen Fehler auslöst. Wenn Ihr Erfolglogger
fehlschlägt, wird der Fehler an den folgenden.catch()
Rückruf weitergeleitet, jedoch nicht an denfail
dazugehörigen Rückrufsuccess
.Hier ist ein Kontrollflussdiagramm :
Um es in synchronem Code auszudrücken:
Das zweite
log
(wie das erste Argument.then()
) wird nur ausgeführt, wenn keine Ausnahme aufgetreten ist. Der markierte Block und diebreak
Aussage fühlen sich ein wenig seltsam, das ist eigentlich das, was Python hattry-except-else
für (empfohlene Lektüre!).Der
catch
Logger behandelt auch Ausnahmen vom erfolgreichen Logger-Aufruf.Soviel zum Unterschied.
Das Argument ist, dass Sie normalerweise Fehler in jedem Schritt der Verarbeitung abfangen möchten und dass Sie sie nicht in Ketten verwenden sollten. Die Erwartung ist, dass Sie nur einen letzten Handler haben, der alle Fehler behandelt. Wenn Sie das "Antipattern" verwenden, werden Fehler in einigen der damaligen Rückrufe nicht behandelt.
Dieses Muster ist jedoch tatsächlich sehr nützlich: Wenn Sie Fehler behandeln möchten, die genau in diesem Schritt aufgetreten sind, und etwas ganz anderes tun möchten, wenn kein Fehler aufgetreten ist - dh wenn der Fehler nicht behoben werden kann. Beachten Sie, dass dies Ihren Kontrollfluss verzweigt . Natürlich ist dies manchmal erwünscht.
Dass Sie Ihren Rückruf wiederholen mussten. Du willst lieber
Sie können dies auch in Betracht ziehen
.finally()
.quelle
.catch
werden Fehler auch in der Erfolgsfunktion fangen .. Ich persönlich finde das extrem falsch , wie Sie mit einem Fehler-Eintrittspunkt am Ende, die von bekommen können mehrere Fehler mehrere Aktionen, aber das ist mein Problem. Sowieso - danke für die Info! Haben Sie kein Online-Kommunikationstool, das Sie gerne teilen möchten, damit ich noch ein paar Fragen stellen kann? : PPromise
Mechaniker auf dieser Seite..done()
ist nicht Teil des Standards, oder? Zumindest listet MDN diese Methode nicht auf. Es wäre hilfreich.done
ist eine Bluebird-Sache, die im Grunde genommen durch diethen
+ unbehandelte Ablehnungserkennung veraltet war .Die beiden sind nicht ganz identisch. Der Unterschied besteht darin, dass das erste Beispiel keine Ausnahme abfängt, die in Ihrem
success
Handler ausgelöst wird . Wenn Ihre Methode also immer nur aufgelöste Versprechen zurückgeben soll, wie dies häufig der Fall ist, benötigen Sie einen nachgestelltencatch
Handler (oder einen weiterenthen
mit einem leerensuccess
Parameter). Sicher, es kann sein, dass Ihrthen
Handler nichts tut, was möglicherweise fehlschlägt. In diesem Fall kann die Verwendung eines 2-Parametersthen
in Ordnung sein.Ich glaube jedoch, dass der Punkt des Textes, mit dem Sie verlinkt haben, im
then
Vergleich zu Rückrufen in Bezug auf die Fähigkeit, eine Reihe von asynchronen Schritten zu verketten, am nützlichsten ist, und wenn Sie dies tatsächlich tun,then
verhält sich die 2-Parameter-Form von subtil nicht ganz wie erwartet aus dem oben genannten Grund. Es ist besonders intuitiv, wenn es in der Mitte der Kette verwendet wird.Als jemand, der viele komplexe asynchrone Dinge erledigt hat und mehr auf solche Ecken gestoßen ist, als ich zugeben möchte, empfehle ich wirklich, dieses Anti-Pattern zu vermeiden und den separaten Handler-Ansatz zu wählen.
quelle
Indem wir die Vor- und Nachteile beider betrachten, können wir eine kalkulierte Vermutung anstellen, welche für die Situation geeignet ist. Dies sind die beiden Hauptansätze zur Umsetzung von Versprechungen. Beide haben Vor- und Nachteile
Vorteile
Nachteile
Vorteile
Nachteile
catch
wenn Sie Fehler behandeln möchten, die durch den erfolgreichen Rückruf ausgelöst wurdenquelle
Einfach erklären:
In ES2018
das bedeutet:
gleich
quelle
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, dann möchten Sie sie an eine asynchrone API übergeben und anschließend die Antwort bearbeiten. Möglicherweise möchten Sie die Antwort zurück in die Datenbank verschieben. Die Handhabung all dieser Workflows mit Ihrem Konzept ist machbar, aber sehr schwer zu verwalten. Die bessere Lösung besteht darinthen().then().then().then().catch()
, alle Fehler in nur einem Fang zu erhalten und die Wartbarkeit des Codes zu gewährleisten.quelle
Verwendung
then()
undcatch()
Unterstützung der Verkettung von Erfolg und Misserfolg bei der Einhaltung des Versprechens.catch()
arbeitet an Versprechen von zurückgegebenthen()
. Es behandelt,then()
behandelt dies nicht.)1. let promiseRef: Promise = this. aTimetakingTask (false); 2. promiseRef 3. .then( 4. (result) => { 5. /* successfully, resolved promise. 6. Work on data here */ 7. }, 8. (error) => console.log(error) 9. ) 10. .catch( (e) => { 11. /* successfully, resolved promise. 12. Work on data here */ 13. });
Dies ist sinnvoll, da das von zurückgegebene Versprechen
then()
keinen Fehler enthält, wenn sich ein Rückruf darum kümmert.quelle
catch
Rückruf scheint falsch.Anstelle von Worten ein gutes Beispiel. Folgender Code (falls das erste Versprechen gelöst wurde):
ist identisch mit:
Aber mit abgelehntem ersten Versprechen ist dies nicht identisch:
quelle