He leído preguntas como Acceso al servicio EventEmitter dentro de CustomHttp donde el usuario usa EventEmitter en su servicio, pero en este comentario se le sugirió que no lo use y que use Observables directamente en sus servicios.
También leí esta pregunta donde la solución sugiere pasar EventEmitter al niño y suscribirse.
Mi pregunta entonces es: ¿Debería o no debería suscribirme manualmente a un EventEmitter? ¿Cómo debo usarlo?
TL;RD :
No, no se suscriba manualmente a ellos, no los use en servicios. Úselos como se muestra en la documentación solo para emitir eventos en componentes. No derrotes la abstracción de angular.
Responder:
EventEmitter es una abstracción angular2 y su único propósito es emitir eventos en componentes. Citando un comentario de Rob Wormald
[...] EventEmitter es realmente una abstracción angular, y debe usarse prácticamente solo para emitir eventos personalizados en componentes. De lo contrario, simplemente use Rx como si fuera cualquier otra biblioteca.
Esto se indica muy claro en la documentación de EventEmitter.
Uso por directivas y componentes para emitir eventos personalizados.
Angular2 nunca nos garantizará que EventEmitter seguirá siendo un Observable. Eso significa refactorizar nuestro código si cambia. La única API a la que debemos acceder es su método emit() . Nunca debemos suscribirnos manualmente a un EventEmitter.
Todo lo dicho anteriormente queda más claro en este comentario de Ward Bell (se recomienda leer el artículo, y la respuesta a ese comentario). Citando para referencia
¡NO cuente con que EventEmitter siga siendo un Observable!
¡NO cuente con que esos operadores Observables estarán allí en el futuro!
Estos quedarán obsoletos pronto y probablemente se eliminen antes del lanzamiento.
Use EventEmitter solo para el enlace de eventos entre un componente secundario y principal. No te suscribas. No llame a ninguno de esos métodos. Llamar solo a
eve.emit()
Su comentario está en línea con el comentario de Rob hace mucho tiempo.
Simplemente utilícelo para emitir eventos desde su componente. Echa un vistazo al siguiente ejemplo.
@Component({ selector : 'child', template : ` <button (click)="sendNotification()">Notify my parent!</button> ` }) class Child { @Output() notifyParent: EventEmitter<any> = new EventEmitter(); sendNotification() { this.notifyParent.emit('Some value to send to the parent'); } } @Component({ selector : 'parent', template : ` <child (notifyParent)="getNotification($event)"></child> ` }) class Parent { getNotification(evt) { // Do something with the notification (evt) sent by the child! } } class MyService { @Output() myServiceEvent : EventEmitter<any> = new EventEmitter(); }Detente ahí... ya estás equivocado...
Con suerte, estos dos ejemplos simples aclararán el uso adecuado de EventEmitter.
EventEmitter es un tipo público y documentado en la API final de Angular Core. Si se basa o no en Observable es irrelevante; si sus métodos documentados de emit y subscribe se ajustan a lo que necesita, entonces continúe y utilícelo.
Como también se indica en los documentos:
Utiliza Rx.Observable pero proporciona un adaptador para que funcione como se especifica aquí: https://github.com/jhusain/observable-spec
Una vez que esté disponible una implementación de referencia de la especificación, cambie a ella.
Así que querían un objeto similar a un Observable que se comportara de cierta manera, lo implementaron y lo hicieron público. Si fuera simplemente una abstracción angular interna que no debería usarse, no lo habrían hecho público.
Hay muchas ocasiones en las que es útil tener un emisor que envíe eventos de un tipo específico. Si ese es tu caso de uso, hazlo. Si/cuando una implementación de referencia de la especificación a la que se vinculan está disponible, debe ser un reemplazo directo, al igual que con cualquier otro polyfill.
Solo asegúrese de que el generador que pasa a la función subscribe() siga la especificación vinculada. Se garantiza que el objeto devuelto tenga un método de cancelación de unsubscribe al que se debe llamar para liberar cualquier referencia al generador (este es actualmente un objeto de Subscription de RxJs, pero de hecho es un detalle de implementación del que no se debe depender).
export class MyServiceEvent { message: string; eventId: number; } export class MyService { public onChange: EventEmitter<MyServiceEvent> = new EventEmitter<MyServiceEvent>(); public doSomething(message: string) { // do something, then... this.onChange.emit({message: message, eventId: 42}); } } export class MyConsumer { private _serviceSubscription; constructor(private service: MyService) { this._serviceSubscription = this.service.onChange.subscribe({ next: (event: MyServiceEvent) => { console.log(`Received message #${event.eventId}: ${event.message}`); } }) } public consume() { // do some stuff, then later... this.cleanup(); } private cleanup() { this._serviceSubscription.unsubscribe(); } }Todas las predicciones de fatalidad y pesimismo fuertemente redactadas parecen provenir de un solo comentario de desbordamiento de pila de un solo desarrollador en una versión preliminar de Angular 2.
Cuando desea tener interacción entre componentes, necesita saber qué son @Input, @Output, EventEmitter y Subjects.
Si la relación entre componentes es padre-hijo o viceversa, usamos @input & @output con emisor de eventos.
@output emite un evento y necesita emitir usando el emisor de eventos.
Si no se trata de una relación padre-hijo... entonces tiene que usar sujetos oa través de un servicio común.