Ist es eine schlechte Übung, eine Konstruktorfunktion eine Versprechung zurückgeben zu lassen?
Ich versuche, erstellen Sie einen Konstruktor für eine blogging-Plattform, und es hat viele asynchrone Operationen vorgeht. Diese reichen von der Ergreifung der Beiträge von Verzeichnissen, analysieren Sie und schickt Sie durch template-engines, etc.
Also meine Frage ist, wäre es unklug zu haben, mein Konstruktor-Funktion zurückzukehren ein Versprechen, anstatt ein Objekt von der Funktion, die Sie aufgerufen new
gegen.
Zum Beispiel:
var engine = new Engine({path: '/path/to/posts'}).then(function (eng) {
//allow user to interact with the newly created engine object inside 'then'
engine.showPostsOnOnePage();
});
Nun, der Benutzer kann auch nicht Versorgung eine Ergänzung Versprechen chain-link:
var engine = new Engine({path: '/path/to/posts'});
//ERROR
//engine will not be available as an Engine object here
Dies könnte ein problem darstellen, da der Benutzer möglicherweise verwechselt werden, warum engine
ist nicht verfügbar, nach Konstruktion.
Den Grund für die Verwendung eines Versprechen im Konstruktor Sinn macht. Ich will das gesamte blog zu funktionieren nach der Bauphase. Jedoch, wie es scheint, ein Geruch fast nicht haben Zugriff auf das Objekt sofort nach dem Aufruf new
.
Habe ich mir überlegt, mit etwas entlang der Linien von engine.start().then()
oder engine.init()
was wieder das Versprechen statt. Aber diese scheinen auch stinkig.
Edit: ist in einem Node.js Projekt.
InformationsquelleAutor der Frage adam-beck | 2014-06-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, es ist eine schlechte Praxis. Ein Konstruktor darf zurück eine Instanz der Klasse, sonst nichts. Es würde mess up die
new
- operator und Vererbung anders.Außerdem, ein Konstruktor darf nur erstellen und initialisieren einer neuen Instanz. Es sollte Datenstrukturen und alle Instanz-spezifischen Eigenschaften, aber nicht ausführen alle Aufgaben. Es sollte ein pure Funktion ohne Nebenwirkungen, wenn möglich, mit allen Vorteilen, die das hat.
Sollten gehen in eine Methode der Klasse. Sie möchten mutieren globalen Staat? Rufen Sie dann diese Verfahren explizit, nicht als eine Nebenwirkung erzeugen eines Objekts. Dieser Anruf geht direkt nach der Instanziierung:
Wenn die Aufgabe asynchron ist, können Sie jetzt einfach wieder ein Versprechen für die Ergebnisse aus der Methode, einfach warten bis es fertig ist.
Ich würde jedoch nicht empfehlen Sie dieses Muster, wenn die Methode (asynchron) mutiert die Instanz-und die anderen Methoden sind davon abhängig, dass, wie das wäre, Sie zu führen Bedarf, zu warten (werden async, auch wenn Sie tatsächlich synchron) und Sie würden schnell eine interne queue-management geht. Nicht code-Instanzen vorhanden, aber eigentlich unbrauchbar.
Fragen Sie sich selbst: braucht man eigentlich die Instanz, ohne die Daten? Konnte Sie es irgendwie?
Wenn die Antwort auf diese Frage ist Keinedann sollten Sie nicht erstellen Sie es, bevor Sie die Daten haben. Die Daten ifself parameter an den Konstruktor, anstatt zu sagen, den Konstruktor, wie die Daten abzurufen (oder der übergabe der Zusage für die Daten).
Dann verwenden Sie eine statische Methode zum laden der Daten, aus denen Sie wieder ein Versprechen. Dann Kette ein Anruf umschließt, die die Daten in eine neue Instanz auf, die:
Dies ermöglicht eine viel größere Flexibilität in der Art und Weise, um den Erwerb der Daten und vereinfacht den Konstruktor einer viel. Sie könnten auch schreiben Sie statische factory-Funktionen, die Rückkehr verspricht für
Engine
Instanzen:InformationsquelleAutor der Antwort Bergi
Ich hatte das gleiche problem und kam mit dieser einfachen Lösung.
Anstatt ein Versprechen aus dem Konstruktor, steckte es in
this.initialization
Eigenschaft, wie das ist:Dann wickeln Sie jede Methode, die in einem Rückruf, der ausgeführt wird, nachdem die Initialisierung so:
Wie sieht es aus API Sicht des Verbrauchers:
Dies funktioniert, da können Sie sich registrieren mehrere Rückrufe versprochen und Sie laufen entweder nachdem Sie aufgelöst wurde, oder, wenn es bereits behoben, die zum Zeitpunkt der Anbringung der Rückruf.
Dies ist, wie mongoskin funktioniert, ausser das es nicht wirklich nutzen verspricht.
Edit: Da ich schrieb, die Antwort habe ich gefallen in der Liebe mit ES6/7 syntax, so gibt es ein weiteres Beispiel mit. Sie können es verwenden, heute mit babel.
Bearbeiten: Sie können dieses Muster nativ mit Knoten 7 und
--harmony
fahne!InformationsquelleAutor der Antwort phaux
Zu vermeiden, die Trennung von Bereichen, verwenden Sie eine Fabrik, um das Objekt zu erstellen.
InformationsquelleAutor der Antwort The Farmer
Den return-Wert aus dem Konstruktor ersetzt das Objekt, das der neue Betreiber, die gerade produziert, so der Rückkehr ein Versprechen ist keine gute Idee. Zuvor eine explizite return-Wert vom Konstruktor verwendet wurde, um das singleton-Muster.
Den besseren Weg in ECMAScript-2017 ist für die Verwendung eines statischen Methoden: Sie haben einen Prozess, der die numerality der statischen.
Welche Methode ausgeführt werden, auf das neue Objekt nach dem Konstruktor kann nur von der Klasse selbst. Kapseln diese innerhalb der Klasse, die Sie verwenden können, verarbeiten.nextTick oder Versprechen.beheben, die Verschiebung der weiteren Ausführung so dass für die Zuhörer werden Hinzugefügt und andere Dinge in Arbeit.starten, die der Aufrufer des Konstruktors.
Da fast alle code wird innerhalb von ein Versprechen, Fehler im Prozess.fatal
Diese Grundidee kann angepasst werden spezielle Kapselung muss.
InformationsquelleAutor der Antwort Harald Rudell