Каково надлежащее использование EventEmitter?

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

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

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

Ответ 1

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

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

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

Это ясно сказано в документации EventEmitter.

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

Что не так с этим связано?

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

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

НЕ рассчитывайте, что EventEmitter будет оставаться наблюдаемым!

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

Они скоро будут устарели и, вероятно, удалены до выпуска.

Использовать EventEmitter только для привязки события между дочерним и родительским компонентами. Не подписывайтесь на него. Не вызывайте ни один из этих методов. Вызывайте только 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 ответ:

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

Ответ 2

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

EventEmitter является общедоступным документированным типом в последнем Angular Core API. Независимо от того, основан ли он на Observable, он не имеет значения; если его документированные методы emit и subscribe соответствуют потребностям, затем используйте его.

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

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

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

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

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

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

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

Все предсказания с предсказанием судьбы и предсказания кажутся следствием одного комментария Qaru от одного разработчика в предварительной версии Angular 2.

Ответ 3

Если вы хотите взаимодействовать между компонентами, вам нужно знать, что такое @Input, @Output, EventEmitter и Subjects.

Если отношение между компонентами является parent- дочерним или наоборот, мы используем @input & @output с генератором событий.

@output генерирует событие, и вам нужно отправить его с помощью генератора событий.

Если это не отношения между родителями и детьми... тогда вы должны использовать предметы или через общий сервис.

Ответ 4

Нет: nono и нет: yesyes. Истина в середине И нет причин бояться из-за следующей версии Angular.

С логической точки зрения, если у вас есть компонент, и вы хотите сообщить другим компонентам о том, что что-то происходит, событие должно быть запущено, и это может быть сделано любым способом, который вы (разработчик) сочтете необходимым. Я не вижу причины, почему бы не использовать его, и я не вижу причины, чтобы использовать его любой ценой. Также имя EventEmitter подсказывает мне событие, происходящее. Я обычно использую его для важных событий, происходящих в Компоненте. Я создаю Службу, но создаю файл Службы внутри Папки компонентов. Таким образом, мой файл службы становится своего рода диспетчером событий или интерфейсом событий, поэтому я могу сразу определить, на какое событие я могу подписаться в текущем компоненте.

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

Некоторые другие парни могут подумать, что использовать Observables напрямую - это круто. В этом случае перейдите непосредственно к Observables. Вы не серийный убийца, делающий это. Если вы не разработчик психопатов, пока программа работает, делайте это.

Ответ 5

@Eric Martinez Я включаю app-child в родительский компонент, он загружает все дочернее приложение в родительский компонент.

Я просто хотел обмениваться данными между родительским компонентом и дочерними компонентами без загрузки дочернего компонента.

Есть ли какая-либо возможность.

заранее спасибо