Was ist der Vorteil von Callbacks gegenüber Ereignissen, wenn Sie noch keine Erfahrung mit node.js haben?

24

Ich bin ein Anfänger von JavaScripter und habe keine wirklichen Kenntnisse darüber, was in der V8-Engine vor sich geht.

Trotzdem genieße ich meine frühen Streifzüge in die Umgebung von node.j sehr, benutze aber ständig events.EventEmitter (), um globale Ereignisse auszulösen, damit ich meine Programme so strukturieren kann, dass sie einem Notifier-Observer entsprechen Muster ähnlich dem, was ich in einem Objective-C- oder Python-Programm schreiben würde.

Ich mache immer Dinge wie diese:

var events = require('events');

var eventCenter = new events.EventEmitter();

eventCenter.on('init', function() {
    var greeting = 'Hello World!';
    console.log('We're in the init function!);
    eventCenter.emit('secondFunction', greeting);
});

eventCenter.on('secondFunction', function(greeting) {
        console.log('We're in the second function!);
        console.log(greeting);
    eventCenter.emit('nextFunction');
});

eventCenter.on('nextFunction', function {
    /* do stuff */
});

eventCenter.emit('init');

Tatsächlich strukturiere ich also den Code von 'async' node.js in Code, der die Dinge in der von mir erwarteten Reihenfolge ausführt, stattdessen "rückwärts", wenn das Sinn macht. Wäre es ein Unterschied, wenn Sie dies in Bezug auf Leistung oder Philosophie rückrufintensiv tun würden? Ist es besser, dasselbe mit Rückrufen anstelle von Ereignissen zu tun?

Laufen
quelle
Wenn Sie feststellen, dass die Codelesbarkeit durch die häufige Verwendung von Rückrufen beeinträchtigt wird, sollten Sie ein Framework verwenden, um die Verwendung von Rückrufen zu beenden. Es braucht ein wenig Anpassung, aber Versprechen können hässliche Rückrufe oft entwirren. Wenn Sie JQuery verwenden, können Sie die Option "Zurückgestellt" verwenden . Eines der einfachsten Versprechen Frameworks ist RSVP .
Brian
Ich bin verwirrt, ich sehe nichts Asynchrones in Ihrem Code, nur Funktionsaufrufe, die überkompliziert geschrieben sind.
Svick

Antworten:

27

Das Schöne an Callbacks ist, dass es dort keinen globalen Status gibt und die Übergabe von Parametern an sie trivial ist. Wenn Sie eine Funktion haben download(URL, callback: (FileData)->void), können Sie erkennen, dass es sich um eine in sich geschlossene Funktion höherer Ordnung handelt, mit der Sie im Wesentlichen eine Funktion "grab this and do that" erstellen können. Sie können sicher sein, dass Ihr Codefluss genau so ist, wie Sie es erwarten, da dieser Rückruf von niemand anderem verarbeitet wird und dieser Rückruf nur die angegebenen Parameter der übergeordneten Funktion kennt. Das macht es modular und einfach zu testen.

Wenn Sie jetzt 5 Dateien gleichzeitig herunterladen und verschiedene Aktionen ausführen möchten, müssen Sie nur fünf dieser Funktionen mit den entsprechenden Rückruffunktionen auslösen. In einer Sprache mit guter anonymer Funktionssyntax kann dies unglaublich leistungsfähig sein.

Ereignisse hingegen sind eher dazu gedacht, 1..*Benutzer über Statusänderungen zu informieren . Wenn Sie am Ende von ein "Download Complete" -Ereignis download(URL)auslösen, bei processDownload()dem ermittelt wird, wo sich die Daten befinden, binden Sie Ihre Implementierungen von Dingen an eine größere Menge von Status. Wie können Sie Downloads jetzt parallelisieren? Wie gehen Sie mit den verschiedenen Downloads unterschiedlich um? Ist download(URL, eventId)elegant Ist downloadAndDoThing(URL)elegant Kaum.

Natürlich machen Sie wie bei allen Dingen Kompromisse. Verschachtelte Rückrufe können die Reihenfolge der Ausführung des Codes machen mehr verwirrend, und der Mangel an einfachen globalen Zugänglichkeit macht es eine schlechte Wahl für etwas , wo Sie tun haben eine 1..*Beziehung zwischen Erzeuger und Verbraucher. Es fällt Ihnen schwerer, Daten weiterzugeben. Wenn Sie jedoch davonkommen, keinen zusätzlichen Status zu haben, ist dies in der Regel trotzdem ein Vorteil.

Ungeachtet. Sie codieren in node.js, wo Rückrufe idiomatisch sind und die Sprache und Bibliotheken auf ihre Verwendung ausgelegt sind. Unabhängig davon, ob Sie in einem Design Vorteile sehen oder nicht, ich denke, es ist fast immer richtig, dass das Schreiben von idiomatischem Code in einer beliebigen Sprache eine weitaus größere Unterstützung bietet und Ihr Leben viel einfacher macht als der Versuch, ihn zu umgehen.

Phoshi
quelle
2

Ich habe noch nie Ereignisse in NodeJS verwendet, aber im Allgemeinen signalisiere ich mit clientseitigen JS-Ereignissen, dass etwas passiert ist, z. B. ein AppointmentBookedEvent, sodass verschiedene Teile einer SPA-Ansicht darauf reagieren können (in einer Zeitleiste anzeigen, laden) in einem Panel, etc).
Die Verwendung von Ereignissen als Signal für die Beendigung einer Methode kann jedoch eine gefährliche Straße sein. Sie können sich nicht darauf verlassen, dass Ereignisse in der Reihenfolge eintreten, in der sie ausgelöst wurden, was zu Zufälligkeiten aller Art führen
kann. Die Verwendung von Ereignissen ist nichts Falsches, aber es gibt ein gewisses Maß an Granularität, das Sie nicht unterschreiten sollten ; Wenn Sie sich an domänenbezogene Ereignisse halten, ist das in Ordnung. Die Benachrichtigung darüber, dass die Methoden abgeschlossen sind, ist jedoch zu detailliert.

Stefan Billiet
quelle
0

Möglicherweise untersuchen Sie die Verwendung der Ereignisse außerhalb des Objekts, das sie ausgibt. In Ihrem Beispiel werden eventCenteranscheinend eigene Ereignisse ausgegeben und verarbeitet. Überlegen Sie, wie sich die Struktur Ihrer Anwendung ändern könnte, wenn andere Objekte beginnen, die Ereignisse zu verarbeiten.

Geben Sie also eventCentermöglicherweise "init" aus, mit dem andere Objekte dann ihren Startcode ausführen können usw.

Dan1701
quelle