Quelle est la bonne utilisation d’un EventEmitter?

J’ai lu des questions comme Access EventEmitter Service dans CustomHttp où l’utilisateur utilise EventEmitter dans son service, mais il a été suggéré dans ce commentaire de ne pas l’utiliser et d’utiliser plutôt Observables directement dans ses services.

J’ai également lu cette question où la solution suggère de transmettre l’événement EventEmitter à l’enfant et de s’y abonner.

Ma question est la suivante: devrais-je ou ne devrais-je pas m’abonner manuellement à un EventEmitter? Comment devrais-je l’utiliser?

Non, vous ne devez pas vous y abonner manuellement.

EventEmitter est une abstraction angular2 dont le seul but est d’émettre des événements dans les composants. Citant un commentaire de Rob Wormald

[…] EventEmitter est en réalité une abstraction angular, et ne devrait être utilisée que pour émettre des événements personnalisés dans les composants. Sinon, utilisez Rx comme s’il s’agissait d’une autre bibliothèque.

Ceci est clairement indiqué dans la documentation de EventEmitter.

Utilisez des directives et des composants pour émettre des événements personnalisés.

Qu’est-ce qui ne va pas avec son utilisation?

Angular2 ne nous garantira jamais que EventEmitter continuera d’être un Observable. Cela signifie donc que nous devons refactoriser notre code s’il change. La seule API à laquelle nous devons accéder est sa méthode emit() . Nous ne devrions jamais souscrire manuellement à un EventEmitter.

Tout ce qui précède est plus clair dans le commentaire de Ward Bell (il est recommandé de lire l’article et la réponse à ce commentaire). Citant pour référence

Ne comptez PAS sur EventEmitter qui continue d’être un object observable!

Ne comptez PAS sur ces opérateurs observables qui seront là dans le futur!

Ceux-ci seront bientôt obsolètes et probablement supprimés avant la publication.

Utilisez EventEmitter uniquement pour la liaison d’événements entre un composant enfant et un composant parent. Ne vous y abonnez pas. N’appelez aucune de ces méthodes. Seulement appeler eve.emit()

Son commentaire est en accord avec le commentaire de Rob depuis longtemps.

Alors, comment l’utiliser correctement?

Utilisez-le simplement pour émettre des événements de votre composant. Jetez un oeil à l’exemple suivant.

 @Component({ selector : 'child', template : `  ` }) class Child { @Output() notifyParent: EventEmitter = new EventEmitter(); sendNotification() { this.notifyParent.emit('Some value to send to the parent'); } } @Component({ selector : 'parent', template : `  ` }) class Parent { getNotification(evt) { // Do something with the notification (evt) sent by the child! } } 

Comment ne pas l’utiliser?

 class MyService { @Output() myServiceEvent : EventEmitter = new EventEmitter(); } 

Arrête-toi là … tu as déjà tort …

Espérons que ces deux exemples simples clarifieront l’utilisation appropriée de EventEmitter.

TL; DR répond:

Non, ne vous abonnez pas manuellement, ne les utilisez pas dans les services. Utilisez-les comme indiqué dans la documentation uniquement pour émettre des événements dans les composants. Ne pas vaincre l’abstraction angular.

Oui, allez-y et utilisez-le.

EventEmitter est un type public documenté dans la dernière API Angular Core. Que ce soit ou non basé sur Observable n’est pas pertinent; Si ses méthodes documentées emit et subscribe vos besoins, alors allez-y et utilisez-les.

Comme indiqué également dans les docs:

Utilise Rx.Observable mais fournit un adaptateur pour le faire fonctionner comme spécifié ici: https://github.com/jhusain/observable-spec

Une fois qu’une implémentation de référence de la spécification est disponible, activez-la.

Ils voulaient donc un object Observable qui se soit comporté d’une certaine manière, ils l’ont mis en œuvre et l’ont rendu public. Si ce n’était qu’une abstraction angular interne qui ne devrait pas être utilisée, ils ne l’auraient pas rendue publique.

Il y a beaucoup de fois où il est utile d’avoir un émetteur qui envoie des événements d’un type spécifique. Si c’est votre cas, allez-y. Si / quand une implémentation de référence des spécifications auxquelles ils sont liés est disponible, cela devrait être un remplacement instantané, comme avec tout autre polyfill.

Assurez-vous simplement que le générateur que vous transmettez à la fonction subscribe() suit la spécification liée. L’object renvoyé est garanti d’avoir une méthode de unsubscribe qui devrait être appelée pour libérer les références au générateur (il s’agit actuellement d’un object d’ Subscription RxJs, mais c’est en fait un détail d’implémentation sur lequel il ne faut pas compter ).

 export class MyServiceEvent { message: ssortingng; eventId: number; } export class MyService { public onChange: EventEmitter = new EventEmitter(); public doSomething(message: ssortingng) { // 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(); } } 

Toutes les prédictions prononcées sur le doom and gloom semblent provenir d’un seul commentaire de Stack Overflow d’un seul développeur sur une version préliminaire d’Angular 2.