web-dev-qa-db-ja.com

Angularコンポーネント:@Output()プロパティとしてEventEmitterの代わりにObservableを使用できますか?

[角度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を使用する方が良いですか?

18
bertrandg

まあ、あなたの状況では、EventEmitterまたはSubjectを使用できます。 EventEmitterSubjectと同じであることがわかります(可能であれば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!'));
  }

  // ...
}
_
7
martin

EventEmitterSubjectを拡張するだけなので、これは驚くべきことではありません(これもDartですでに確認されています)。

独自のクラスを使用して、既存のコードを壊すことなく、後で実装を変更できます。

したがって、この抽象化を回避することは最善のアイデアではないかもしれません。あなたが不利な点を知っていて、それを受け入れる用意があるなら、もちろんそれを行うことができます。

10

EventEmitterを選択する2つの理由

  1. Angular EventEmitterは、必要に応じて確実に非同期でイベントを配信できます。レスポンシブなユーザーエクスペリエンスに適しています。
  2. 下線の実装をカプセル化します。いつか、Angularの次のバージョンでは、EventEmitterの新しいものに依存するイベントバインディングが更新されます。Subjectを頻繁に使用すると、プロジェクトに障害が発生します。これについては不明ですが、避けてください。

Angular EventEmitterはRxJS Subjectを拡張し、これまでに3つのメソッドのみを使用しています:1)constructor()、2)subscribe(next, error, complete)および3)新しいメソッドemit(value) {super.next(value);}

new EventEmitter(true)の場合、非同期でイベントを配信します

_    constructor(isAsync = false) {
        super();
        this.__isAsync = isAsync;
    }
_

EventEmitter.subscribe()は、_this._isAsync_に従ってasync配信イベントに対して何かを行います。

0
xuemind