Novato en node.js, ¿cuál es la ventaja obtenida al usar devoluciones de llamada sobre eventos?

24

Soy un JavaScripter novato y no tengo un conocimiento real de lo que sucede dentro del motor V8.

Dicho esto, realmente disfruto de mis incursiones tempranas en el entorno de node.js, pero descubro que estoy constantemente usando events.EventEmitter () como un medio para emitir eventos globales para poder estructurar mis programas para adaptarlos a un notificador-observador patrón similar a lo que escribiría en decir un programa Objective-C o Python.

Siempre me encuentro haciendo cosas como esta:

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');

Entonces, en efecto, solo estoy estructurando el código 'async' node.js en un código que haga las cosas en el orden que espero, en lugar de eso estoy "codificando hacia atrás" si eso tiene sentido. ¿Habría alguna diferencia en hacer esto de una manera de devolución de llamada, ya sea en cuanto al rendimiento o la filosofía? ¿Es mejor hacer lo mismo usando devoluciones de llamada en lugar de eventos?

Empujoncito
fuente
Si encuentra que la legibilidad de su código se ve afectada debido al uso intensivo de devoluciones de llamada, considere hacer uso de un marco para ajustar su uso de devoluciones de llamada. Requiere un poco de ajuste, pero las promesas a menudo pueden desenredar las devoluciones de llamadas feas. Si está utilizando JQuery, podría usar diferido . Uno de los marcos de promesa más simples es RSVP .
Brian
Estoy confundido, no veo nada asíncrono en su código, solo llamadas de función escritas de una manera demasiado complicada.
svick

Respuestas:

27

Lo bueno de las devoluciones de llamada es que no hay un estado global allí, y pasarles parámetros es trivial. Si tiene una función, download(URL, callback: (FileData)->void)entonces puede saber que es una función autónoma de orden superior que esencialmente le permite construir una función de "agarrar esto y hacer aquello". Puede estar seguro de que su flujo de código es exactamente como espera, porque nadie más tiene un control sobre esa devolución de llamada, y esa devolución de llamada no conoce nada más que los parámetros dados de la función principal. Eso lo hace modular y fácil de probar.

Si ahora desea descargar 5 archivos en paralelo y hacer cosas diferentes, solo necesita activar cinco de estas funciones con las funciones de devolución de llamada apropiadas. En un lenguaje con buena sintaxis de función anónima, esto puede ser increíblemente poderoso.

Los eventos, por otro lado, están más diseñados para notificar a los 1..*usuarios sobre algún cambio de estado. Si activa un evento de "descarga completa" al final de download(URL), que se inicia y processDownload()que sabe dónde encontrar los datos, está vinculando sus implementaciones de cosas a una mayor cantidad de estado. ¿Cómo paralelizas las descargas ahora? ¿Cómo manejas las diferentes descargas de manera diferente? Es download(URL, eventId)elegante? Es downloadAndDoThing(URL)elegante? Apenas.

Por supuesto, como con todas las cosas, estás haciendo compensaciones. Devoluciones de llamada anidados pueden hacer que el orden de ejecución de código más confuso, y la falta de fácil accesibilidad global hace una mala elección para cualquier cosa en la que hacer una 1..*relación entre el productor y el consumidor. Le resulta más difícil pasar los datos, pero si puede salirse con la suya sin tener un estado adicional, entonces eso suele ser un beneficio de todos modos.

Independientemente. Estás codificando en node.js donde las devoluciones de llamada son idiomáticas, y el lenguaje y las bibliotecas están diseñados para su uso. Ya sea que vea ventajas en un diseño u otro, creo que casi siempre es cierto que escribir código idiomático en cualquier idioma tendrá un soporte mucho mayor y hará que su vida sea mucho más fácil que tratar de eludirlo.

Phoshi
fuente
2

Nunca he usado eventos en NodeJS, pero en general para lo que uso los eventos JS del lado del cliente es para indicar que algo ha sucedido, por ejemplo, un evento AppointmentBookedEvent, para que diferentes partes de una vista SPA puedan reaccionar a eso (mostrarlo en una línea de tiempo, cargarlo en un panel, etc.
Pero usar eventos para indicar que un método se ha completado puede ser un camino peligroso por recorrer. No puede confiar en que los eventos lleguen en el mismo orden en que fueron disparados, por lo que eso podría conducir a todo tipo de aleatoriedad ...
No hay nada de malo en usar eventos, pero hay un cierto nivel de granularidad que no debe pasar ; si te limitas a los eventos de dominio, está bien. Pero notificar que los métodos han terminado es demasiado granular.

Stefan Billiet
fuente
0

Algo que puede explorar es el uso de los eventos fuera del objeto que los está emitiendo. En su ejemplo, eventCenterparece emitir y manejar sus propios eventos. Considere cómo la estructura de su aplicación podría cambiar si otros objetos comienzan a manejar los eventos.

Entonces, eventCenterpodría emitir "init", que otros objetos podrían manejar para hacer su código de inicio, etc.

Dan1701
fuente