Угловой компонент: могу ли я использовать Observable вместо EventEmitter как свойство @Output()?

[угловой 2.4.5]

Я пробовал и, похоже, работает как EventEmitter:

  • Мой компонент извне:

    <split (visibleTransitionEnd)="log($event)"></split>
    
  • Внутри компонента:

    @Output() visibleTransitionEnd: Observable<string>
    observer: Observer;
    
    constructor() {
      const myObs = new Observable(observer => this.observer = observer);
    
      this.visibleTransitionEnd = myObs
        .map(x => '> ' + x + ' <')
        .debounceTime(20)
        .do(() => console.log('here we are!'));
    }
    
  • Затем я могу вызвать внутренний компонент:

    // needed condition because if nobody subscribe 'visibleTransitionEnd' > no observer!
    if(this.observer) this.observer.next('test');
    

Посмотреть этот плункер

Мне это нравится, потому что внутри моего компонента нет подписки.

Но это плохой способ достичь этого? Что такое риск/не так?

Лучше ли использовать Subject?

Ответ 1

Ну, в вашей ситуации вы можете использовать EventEmitter или Subject. Вы можете видеть, что EventEmitter похож на Subject (хотя рекомендуется использовать EventEmitter если можно). https://github.com/angular/angular/blob/master/modules/%40angular/facade/src/async.ts

Функция Observable.create (или new Observable()) не предназначена для использования подобным образом. Внутренняя функция должна излучать значения наблюдателю и возвращать функцию разрыва (освободить ресурсы или что-то еще). Не быть сохраненным как собственность.
Однако я не уверен, какие последствия он может иметь (утечки памяти?).

Поэтому скорее используйте Subject:

export class SplitComponent implements OnDestroy {
  @Output() visibleTransitionEnd: Observable<string>
  visibleTransitionEndObserver: Subject;

  constructor() {
    const subject = new Subject();

    this.visibleTransitionEnd = subject.asObservable()
      .map(x => '> ' + x + ' <')
      .debounceTime(20)
      .do(() => console.log('here we are!'));
  }

  // ...
}

Ответ 2

EventEmitter просто расширяет Subject, поэтому это неудивительно (и я тоже это видел в Dart).

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

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