Jakie jest właściwe zastosowanie Eventemittera?

Czytałem takie pytania jak Dostęp do usługi EventEmitter wewnątrz CustomHttp gdzie użytkownik używa EventEmitter w swoim serwisie, ale został zasugerowany w tym komentarzu nie używać go, a zamiast tego używać Obserwabli bezpośrednio w swoich usługach.

Czytam też to pytanie gdzie rozwiązanie sugeruje, aby przekazać Zdarzenie dziecku i zapisać się do niego.

Moje pytanie brzmi: Czy powinienem, czy nie powinienem ręcznie subskrybować Eventemitera? Jak mam go używać?

Author: Community, 2016-03-18

2 answers

Nie, Nie powinieneś subskrybować go ręcznie.

EventEmitter jest abstrakcją angular2 i jej jedynym celem jest emitowanie zdarzeń w komponentach. Cytując komentarz od Rob Wormald

[...] EventEmitter jest tak naprawdę abstrakcją kątową i powinien być używany tylko do emitowania niestandardowych zdarzeń w komponentach. W przeciwnym razie, po prostu użyj Rx, jakby to była jakaś inna biblioteka.

To jest powiedziane bardzo jasno w przypadku dokumentacja.

Używa dyrektyw i komponentów do emitowania niestandardowych zdarzeń.

Co jest złego w używaniu go?

Angular2 nigdy nie zagwarantuje nam, że EventEmitter będzie nadal obserwowalny. Oznacza to refaktoryzację naszego kodu, jeśli się zmieni. Jedynym API, do którego mamy dostęp, jest jego Metoda emit(). Nigdy nie powinniśmy zapisywać się ręcznie do Eventemittera.

Wszystko powyżej jest bardziej jasne w komentarzu (polecam przeczytaj artykuł i odpowiedź na ten komentarz). Cytowanie dla odniesienia

Nie licz na to, że EventEmitter będzie obserwowalny!

Nie licz na tych obserwowalnych operatorów, którzy będą tam w przyszłości!

Zostaną one wycofane wkrótce i prawdopodobnie usunięte przed wydaniem.

Użyj EventEmitter tylko do powiązania zdarzeń między komponentem potomnym i rodzicem. Nie Subskrybuj go. Nie wywołaj żadnej z tych metod. Tylko zadzwoń eve.emit()

Jego komentarz jest zgodny z komentarzem Roba dawno temu.

Więc, jak go prawidłowo używać?

Po prostu użyj go do emitowania zdarzeń z twojego komponentu. Spójrz na poniższy przykład.

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

Jak tego nie używać?

class MyService {
    @Output() myServiceEvent : EventEmitter<any> = new EventEmitter();
}
Zatrzymaj się... już się mylisz...

Miejmy nadzieję, że te dwa proste przykłady wyjaśnią właściwe użycie Eventemittera.

TL; DR odpowiedź:

Nie, Nie Subskrybuj ręcznie do nich, nie używaj ich w usługach. Używaj ich tak, jak pokazano w dokumentacji tylko do emitowania zdarzeń w komponentach. Nie pokonaj abstrakcji angular.

 251
Author: Eric Martinez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:04

Tak, śmiało.

EventEmitter jest publicznym, udokumentowanym typem w końcowym interfejsie API Angular Core. Niezależnie od tego, czy jest ona oparta na Observable, nie ma znaczenia; jeśli jej udokumentowane metody emit i subscribe pasują do tego, czego potrzebujesz,użyj jej.

Jak również stwierdzono w dokumentach:

Używa Rx.Obserwowalny, ale zapewnia adapter, aby działał jak określono tutaj: https://github.com/jhusain/observable-spec

Once a reference implementacja specyfikacji jest dostępna, przełącz się na nią.

Więc chcieli Observable podobnego obiektu, który zachowywał się w określony sposób, zaimplementowali go i upublicznili. Gdyby była to tylko wewnętrzna abstrakcja kątowa, której nie należy używać, nie upublicznialiby jej.

Jest wiele razy, kiedy warto mieć emiter, który wysyła zdarzenia określonego typu. Jeśli to Twój przypadek użycia, śmiało. If / when a reference implementation of the spec they link to jest dostępny, powinien być zamiennikiem drop-in, podobnie jak w przypadku każdego innego polyfill.

Upewnij się tylko, że generator, który PRZEKAZUJESZ do funkcji subscribe(), jest zgodny ze specyfikacją linked spec. Zwracany obiekt ma gwarancję posiadania metody unsubscribe, która powinna być wywołana w celu uwolnienia wszelkich odwołań do generatora (obecnie jest to obiekt RxJs Subscription , ale jest to w rzeczywistości szczegół implementacji, od którego nie powinno się zależeć).

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

Wszystkie mocno sformułowane doom i przewidywania mroku wydają się wynikać z pojedynczego komentarza przepełnienia stosu od jednego dewelopera na przedpremierowej wersji Angular 2.

 45
Author: Toby J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-07 21:29:57