Wie kann man Versprechen verweigern (und richtig nutzen)?

8

Kurzgeschichte :

  • Wenn Sie über Versprechen / A + sprechen, was ist der richtige Weg, ein Versprechen abzulehnen - einen Fehler zu melden? Aber wenn ich das catch vermisse - wird meine ganze App blasen!

  • Wie benutzt man promisify und welche Vorteile hat es (vielleicht müssen Sie die längere Version lesen)?

  • Ist .then(success, fail) wirklich ein Anti-Pattern und sollte ich immer verwenden .then(success).catch(error) ?

Längere Version , beschrieben als echtes Lebensproblem (würde jemanden zum Lesen lieben):

Ich habe eine Bibliothek, die Bluebird (A + Promise-Implementierungsbibliothek) verwendet, um Daten aus der Datenbank zu holen (über Sequelize ). Jede Abfrage gibt ein Ergebnis zurück, aber manchmal ist sie leer (versucht, etwas auszuwählen, aber es gab keine). Das Versprechen geht in die Funktion result , weil es keinen Grund für einen Fehler gibt (kein Ergebnis ist kein Fehler). Beispiel:

%Vor%

Ich möchte das umbrechen und prüfen, ob das Ergebnis leer ist (kann nicht überall in meinem Code überprüft werden). Ich habe das getan:

%Vor%

Wenn Sie immer noch bei mir sind - ich hoffe, Sie werden verstehen, was los ist. Ich möchte irgendwie die Fehlerfunktion auslösen (wo "ERROR-Funktion" ist). Die Sache ist - ich weiß nicht wie. Ich habe diese Dinge ausprobiert:

%Vor%

Wie Sie an meinen Kommentaren (und pro Spezifikation) sehen können, funktioniert das Auslösen eines Fehlers gut. Aber, es gibt ein großes aber - wenn ich die .catch Aussage verpasse, explodiert meine ganze App.

Warum will ich das nicht? Nehmen wir an, ich möchte einen Zähler in meiner Datenbank erhöhen. Ich interessiere mich nicht für das Ergebnis - ich mache nur HTTP-Anfrage .. So kann ich incrementInDB() aufrufen, die die Fähigkeit hat, Ergebnisse zurückzugeben (auch aus Testgründen), so gibt es throw new Error , wenn es fehlgeschlagen ist. Aber da mir die Antwort egal ist, werde ich manchmal keine .catch-Anweisung hinzufügen , oder? Aber jetzt - wenn ich nicht (absichtlich oder durch Verschulden) - ich am Ende mit Ihrer Knoten-App herunter.

Ich finde das nicht sehr nett . Gibt es einen besseren Weg, um es auszuarbeiten, oder muss ich mich nur damit befassen?

Ein Freund von mir hat mir geholfen und ich habe ein neues Versprechen gebraucht, um das Problem zu lösen:

%Vor%

Funktioniert wie ein Zauber! Aber Ich habe Folgendes: Promise Anti Patterns - Wiki Artikel geschrieben von Petka Antonov, Schöpfer von Bluebird (A + Umsetzung). Es wird ausdrücklich gesagt, dass dies falsch ist.

Also meine zweite Frage ist - ist es so? Wenn ja - warum? Und was ist der beste Weg?

Vielen Dank für das Lesen, ich hoffe, dass jemand Zeit für mich hat, um es zu beantworten :) Ich sollte hinzufügen, dass ich mich nicht zu sehr auf Frameworks verlassen wollte, also sind Sequelize und Bluebird einfach Dinge mit dem ich gearbeitet habe. Mein Problem ist mit Promises als global, nicht mit diesem bestimmten Rahmen.

    
Andrey Popov 27.02.2015, 09:18
quelle

2 Antworten

8

Bitte stellen Sie nur eine Frage pro Beitrag: -)

  

Ist .then(success, fail) wirklich ein Anti-Muster und sollte ich immer .then(success).catch(error) benutzen?

Nein. Sie tun nur verschiedene Dinge , aber sobald Sie wissen, dass Sie das Passende auswählen können.

  

Wie benutzt man promisify und welche Vorteile hat es?

Ich denke, die Bluebird Promisification-Dokumentation erklärt das ziemlich gut - es ist an < a href="https://stackoverflow.com/q/22519784/1048572"> konvertieren Sie ein Callback-API zu einem, das Versprechen zurückgibt.

  

Über Promises / A + sprechen, was ist der richtige Weg, ein Versprechen abzulehnen - einen Fehler zu werfen?

Ja, ein Fehler ist völlig in Ordnung. Innerhalb eines then Callbacks können Sie werfen und es wird automatisch abgefangen, was zur Ablehnung des Ergebnisversprechens führt.

Sie können auch return Promise.reject(new Error(…)); ; beide werden absolut die gleiche Wirkung haben.

  

Ein Freund von mir hat mir geholfen, und ich habe ein neues Versprechen gebraucht, um Dinge zu reparieren, wie folgt: [...]

Nein. Sie sollten das wirklich nicht verwenden . Verwenden Sie einfach then und werfen Sie dort ein abgelehntes Versprechen ein oder geben Sie es zurück.

  

Aber wenn ich die Fangaussage vermisse - meine ganze App wird blasen!

Nein, wird es nicht. Beachten Sie, dass .catch() method keine try catch -Anweisung ist - der Fehler wird bereits abgefangen, wenn Ihr then -Rückruf aufgerufen wurde. Es wird dann nur an den catch -Rückruf als Argument übergeben, der Aufruf .catch() ist nicht erforderlich, um Ausnahmen zu erfassen.

Und wenn Sie .catch() verpassen, wird Ihre App nicht ausgelöst. Alles was passiert ist, dass Sie ein abgelehntes Versprechen herumliegen haben, der Rest Ihrer App wird davon nicht betroffen sein. Sie erhalten ein unbehandeltes Zurückweisungsereignis , das global behandelt .

Natürlich sollte nicht passieren; Jede Versprechen Kette ( nicht jede Versprechen Instanz ) sollte mit einem .catch() beendet werden, das Fehler entsprechend behandelt. Aber Sie brauchen definitiv nicht .catch() in jeder Hilfsfunktion, wenn es ein Versprechen an eine andere Stelle zurückgibt, dann werden normalerweise Fehler vom Aufrufer behandelt.

    
Bergi 27.02.2015 10:47
quelle
5
  

Über Promises / A + sprechen, was ist der richtige Weg, ein Versprechen abzulehnen - einen Fehler zu werfen? Aber wenn ich den Haken verpasse - meine ganze App wird blasen!

Und wenn Sie Rückkehrcodes verwenden, um Fehler anstelle von Ausnahmen zu signalisieren, führt die fehlende Überprüfung zu kleinen Fehlern und unberechenbarem Verhalten. Es ist ein Fehler, die Fehler nicht zu vergessen, aber in einem so unglücklichen Fall zu explodieren, ist häufiger besser als es im beschädigten Zustand weitermachen zu lassen.

Das Debuggen vergessener Fehlercode-Prüfung, die nur durch die Anwendung offensichtlich ist, die sich seltsam an einem nicht verwandten Ort der Fehlerquelle verhält, ist leicht um viele Größenordnungen teurer als das Debuggen eines vergessenen Fangs, weil Sie die Fehlermeldung haben , Fehlerquelle und Stack-Trace. Wenn Sie also Produktivität im typischen Anwendungsentwicklungsszenario wünschen, gewinnen Ausnahmen mit ziemlich großem Vorsprung.

  

.dann (Erfolg, fehlgeschlagen)

Dies ist normalerweise ein Signal dafür, dass Sie Versprechungen als verherrlichte Rückrufe verwenden, bei denen die Rückrufe einfach getrennt weitergegeben werden. Dies ist offensichtlich ein Anti-Muster, da Sie aus der Verwendung von Versprechen auf diese Weise keinen Nutzen ziehen können. Wenn das nicht der Fall ist, dann machen Sie Ihren Code nur geringfügig weniger lesbar im Vergleich zur Verwendung von .catch() , ähnlich wie method(true, true, false) viel weniger lesbar ist als method({option1: true, option2: true, option3: false}) .

  

Wie Promisify zu verwenden und welche Vorteile haben Sie (vielleicht müssen Sie die längere Version lesen)?

Die meisten Module stellen nur eine Callback-Schnittstelle zur Verfügung, promisify verwandelt eine Callback-Schnittstelle automatisch in eine Promise-Schnittstelle. Wenn Sie solchen Code manuell schreiben (mit deferred oder new Promise ), verschwenden Sie Ihre Zeit.

  

Also meine zweite Frage ist - ist es so? Wenn ja - warum? Und was ist der beste Weg?

Der beste Weg ist, das Versprechen zu verketten:

%Vor%

Es ist besser, weil es einfacher, kürzer, lesbarer und weit weniger fehleranfällig ist, genau dasselbe zu tun.

    
Esailija 27.02.2015 10:36
quelle