Quel est l'usage approprié d'un EventEmitter?

j'ai lu des questions comme accès au Service EventEmitter à L'intérieur de CustomHttp lorsque l'utilisateur utilise EventEmitter dans son service, mais il a été suggéré dans ce commentaire ne pas l'utiliser et utiliser plutôt Observables directement dans ses services.

j'ai aussi lu ceci question où la solution suggère de passer L'EventEmitter à l'enfant et de s'y abonner.

My la question est alors : dois-je, ou ne dois-je pas souscrire manuellement à un EventEmitter? Comment devrais-je l'utiliser?

146
demandé sur Community 2016-03-18 08:20:38

2 réponses

Non, vous ne devez pas vous inscrire manuellement.

EventEmitter est un angular2 l'abstraction et son seul but est d'émettre des événements dans les composants. Citant un commentaire de Rob Wormald

[...] EventEmitter est vraiment une abstraction angulaire, et devrait être utilisé à peu près seulement pour l'émission d'événements personnalisés dans les composants. Sinon, utilisez Rx comme si c'était une autre bibliothèque.

cela est indiqué très clairement dans la documentation D'EventEmitter.

utilisation par les directives et les composants pour émettre des événements personnalisés.

Qu'y a-t-il de mal à l'utiliser?

Angular2 ne nous garantira jamais que EventEmitter continuera d'être un Observable. Cela signifie donc qu'il faut remanier 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.

Tous les mentionnés ci-dessus est plus clair dans cette Paroisse de Bell commentaire (recommandé pour lire l'article, et le réponse ce commentaire). Citant pour référence

ne comptez pas sur EventEmitter pour continuer à être un Observable!

ne comptez pas sur ces opérateurs observables pour l'avenir!

ceux-ci seront dépréciés bientôt et probablement enlevés avant la libération.

N'utiliser EventEmitter que pour la liaison d'événement entre un composant enfant et un composant parent. Ne pas y souscrire. Ne pas appeler l'une de ces méthodes. Seulement appeler eve.emit()

son commentaire est en ligne avec celui de Rob il y a longtemps.

Alors, comment l'utiliser correctement?

utilisez-le simplement pour émettent des événements de votre composant. Prendre un coup d'oeil a l'exemple suivant.

@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!
    }
}

Comment ne pas l'utiliser?

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

Arrêtez-vous là... vous êtes déjà mal...

espérons que ces deux exemples simples clarifieront L'usage approprié d'EventEmitter.

TL;DR answer:

Non, ne vous abonnez pas manuellement à eux, ne les utilisez pas dans service. Utilisez - les comme indiqué dans la documentation uniquement pour émettre des événements dans les composants. Ne battez pas l'abstraction d'angular.

251
répondu Eric Martinez 2017-05-23 12:03:04

oui, allez-y et utilisez-le.

EventEmitter est un public, documenté type , dans la dernière Angulaire de Base de l'API. Qu'elle soit ou non basée sur Observable n'est pas pertinent; si ses méthodes documentées emit et subscribe conviennent à ce dont vous avez besoin, alors allez de l'avant et utilisez-la.

comme aussi indiqué dans le docs:

Utilise Rx.Observables, mais qui 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, passez à elle.

donc ils voulaient un Observable comme objet qui se comportait d'une certaine manière, ils l'ont mis en œuvre, et l'ont rendu public. Si ce n'était qu'une abstraction angulaire interne qui ne devrait pas être utilisée, ils ne l'auraient pas rendue publique.

là sont beaucoup de fois, il est utile de disposer d'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 de la spécification à laquelle ils se rapportent est disponible, il devrait s'agir d'un remplacement direct, tout comme pour tout autre polyfill.

assurez-vous que le Générateur que vous passez à la fonction subscribe() suit la spécification liée. L'objet retourné est garanti d'avoir une méthode unsubscribe qui devrait être appelé à libérer toute référence au générateur (il s'agit actuellement d'un RxJs Subscription objet mais c'est en fait un détail de mise en œuvre qui ne devrait pas dépendre).

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();
    }
}

toutes les prédictions pessimistes et pessimistes fortement formulées semblent provenir d'un seul commentaire de débordement de pile d'un seul développeur sur une version pré-release D'Angular 2.

45
répondu Toby J 2017-11-07 21:29:57