Как правильно использовать EventEmitter?


Я читал такие вопросы, как доступ к службе EventEmitter внутри CustomHttp где пользователь использует EventEmitter в своем сервисе, но он был предложен в этом комментарий не использовать его, а использовать вместо этого наблюдаемые непосредственно в его услугах.

Я тоже читал этот вопрос где решение предлагает передать EventEmitter ребенку и подписаться на него.

мой вопрос тогда: должен ли я, или я не должен подписаться вручную на EventEmitter? Как я должен его использовать?

2 146

2 ответа:

нет, вы не должны подписываться на него вручную.

EventEmitter - это абстракция angular2, и ее единственная цель-излучать события в компонентах. Цитирую комментарий от Роба Wormald

[...] EventEmitter действительно является угловой абстракцией и должен использоваться в значительной степени только для испускания пользовательских событий в компонентах. В противном случае, просто используйте Rx, как если бы это была любая другая библиотека.

это действительно сказал очистить в документации EventEmitter.

использование директив и компонентов для создания пользовательских событий.

что плохого в его использовании?

Angular2 никогда не гарантирует нам, что EventEmitter будет продолжать быть наблюдаемым. Так что это означает рефакторинг нашего кода, если он изменится. Единственный API, к которому мы должны получить доступ, - это его emit() метод. Мы никогда не должны подписываться вручную на EventEmitter.

все изложенное выше более понятно в этой палате Белла комментарий (рекомендуется прочитать статью, а то ответ на это замечание). Цитирование для справки

не рассчитывайте на то, что EventEmitter продолжает быть наблюдаемым!

не рассчитывайте на то, что эти наблюдаемые операторы будут там в будущем!

они будут устарели в ближайшее время и, вероятно, удалены до выпуска.

использовать EventEmitter только для привязки событий между a дочерний и родительский компонент. Не Подписывайтесь на него. Не вызывайте ни один из этих методов. Только позвоните eve.emit()

его комментарий соответствует комментарию Роба давным-давно.

Итак, как правильно его использовать?

просто используйте его для генерации событий из вашего компонента. Взгляните на следующий пример.

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

остановитесь прямо здесь... ты уже ошибаешься...

надеемся, что эти два простых примера прояснят правильное использование EventEmitter.

TL; DR ответ :

нет, не Подписывайтесь на них вручную, не используйте их в сервисах. Используйте их как показано в документации только для создания событий в компонентах. Не побеждайте абстракцию углового.

Да, идите и используйте его.

EventEmitter это открытый, документированный типа в окончательном угловом ядре API. Независимо от того, основан ли он на Observable не имеет значения; если его документированных emit и subscribe методы подходят то, что вам нужно, а затем идти вперед и использовать его.

Как также указано в документах:

Использует Rx.Наблюдаемый, но предоставляет адаптер, чтобы заставить его работать, как указано здесь: https://github.com/jhusain/observable-spec

как только эталонная реализация спецификации доступна, переключитесь на нее.

так они хотели Observable как объект, который вел себя определенным образом, они реализовали его, и сделал это публично. Если бы это была просто внутренняя угловая абстракция, которая не должна была использоваться, они не сделали бы ее публичной.

есть много раз, когда полезно иметь эмиттер, который отправляет события определенного типа. Если это ваш вариант использования, идите на это. Если/когда эталонной реализацией спецификации, на которые они ссылаются, она должна быть заменой, как и в любом другом полифилл.

просто убедитесь, что генератор вы передаете в subscribe() функция следует за связанной спецификацией. Возвращаемый объект гарантированно имеет unsubscribe метод, который должен быть вызван, чтобы освободить все ссылки на генератор (это в настоящее время RxJs Subscription объект но это действительно деталь реализации, от которой не следует зависеть).

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

все сильно сформулированные предсказания doom и gloom, похоже, происходят из одного комментария переполнения стека от одного разработчика на предварительной версии Angular 2.