web-dev-qa-db-ja.com

EventEmitterの正しい使い方は何ですか?

CustomHttp内のEventEmitterサービスへのアクセス のような質問を読みましたが、ここではユーザーが自分のサービスでEventEmitterを使用していますが、この コメント では使用せずに直接Observablesを使用することをお勧めします。彼のサービスで。

私はまた、この解決法がEventEmitterを子供に渡してそれを購読することを示唆している question を読んだ。

私の質問はそれです:私は、EventEmitterを手動で購読すべきですか、それとも購読しないべきですか?どうやって使うの?

176
Eric Martinez

いいえ、手動で購読するべきではありません。

EventEmitter はangular2抽象化であり、その唯一の目的はコンポーネント内のイベントを発行することです。 コメント / Rob Wormaldからの引用

[...] EventEmitterは実際にはAngular抽象概念であり、コンポーネント内でカスタムイベントを発行するためだけに使用されるべきです。それ以外の場合は、Rxを他のライブラリのように使用してください。

これはEventEmitterのドキュメントにはっきりと述べられています。

カスタムイベントを発行するためにディレクティブとコンポーネントによって使用されます。

それを使うことの何が問題になっていますか?

Angular 2は、EventEmitterがObservableであり続けることを保証するものではありません。つまり、コードが変更された場合にそれをリファクタリングするということです。アクセスしなければならない唯一のAPIはそのemit()メソッドです。手動でEventEmitterを購読してはいけません。

このWard Bellの comment では、上記のすべてがより明確になっています(記事を読むこと、およびそのコメントに対する answer を読むことをお勧めします)。参考のために引用

EventEmitterが引き続きObservableであることを頼りにしないでください。

Observableの演算子が将来そこにあるとは思わないでください。

これらは近々廃止予定で、おそらくリリース前に削除されるでしょう。

EventEmitterは、子コンポーネントと親コンポーネント間のイベントバインディングにのみ使用します。購読しないでください。これらのメソッドを呼び出さないでください。 eve.emit()のみを呼び出す

彼のコメントは昔のRobのコメントと一致している。

それで、それを正しく使う方法は?

単にあなたのコンポーネントからイベントを発行するためにそれを使用してください。次の例を見てください。

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

すぐそこでやめてください...あなたはもう間違っています...

うまくいけば、これら2つの簡単な例がEventEmitterの正しい使い方を明確にするでしょう。

TL; DR 回答:

いいえ、手動で購読したり、サービスで使用したりしないでください。コンポーネントでイベントを発行するためだけに、ドキュメントに示されているようにそれらを使用してください。角度の抽象化を破らないでください。

290
Eric Martinez

はい、どうぞ。

最後のAngular Core APIでは、EventEmitter公開され、ドキュメント化された型 です。それがObservableに基づいているかどうかは関係ありません。文書化されたemitおよびsubscribeメソッドが必要なものに適している場合は、先に進んでそれを使用してください。

ドキュメントにも記載されているように:

Rx.Observableを使用しますが、ここで指定されているように動作させるためのアダプターを提供します。 https://github.com/jhusain/observable-spec

仕様の参照実装が利用可能になったら、それに切り替えます。

それで彼らはある方法で振る舞うObservableのようなオブジェクトを望み、それを実装し、そしてそれを公開しました。それが単に使用されるべきでない内部のAngular抽象化であったならば、彼らはそれを公表しなかったでしょう。

特定のタイプのイベントを送信するエミッターがあると便利な場合がたくさんあります。それがあなたのユースケースなら、それを行ってください。それらがリンクしているspecの参照実装が利用可能であるならば、他のpolyfillと同じように、それはドロップイン置換えであるべきです。

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と暗闇の予測はすべて、プレリリース版のAngular 2に関する1人の開発者からの1回のStack Overflowコメントに由来するようです。

71
Toby J

コンポーネント間の相互作用が必要な場合は、@ Input、@ Output、EventEmitter、およびSubjectsが何であるかを知る必要があります。

コンポーネント間の関係が親子関係にある場合、またはその逆の場合は、@input&@outputをイベントエミッタと共に使用します。

@outputはイベントを発行します。イベントエミッタを使用して発行する必要があります。

それが親子関係ではないならば、それからあなたは主題を使うか、または共通のサービスを通してしなければなりません。

1
Akhil

かなり論理的な観点から。あなたがコンポーネントを持っていて、何かが起こったことを他のコンポーネントに知らせたいのであれば、イベントが起動されるべきです。使用しない理由がわかりません。また、EventEmitterの名前は、私にイベントが起こっていることをかなり示唆しています。私は通常Componentスコープで起こる重要なイベントにそれを使います。サービスを作成しますが、コンポーネントフォルダ内にサービスファイルを作成します。したがって、私のServiceファイルは一種のEvent ManagerまたはEvent Interfaceになるので、現在のコンポーネントでどのイベントをサブスクライブできるかが一目でわかります。

私は知っていますか?私はちょっと古い魅惑的な開発者です。

しかしこれはイベント駆動開発パターンと呼ばれます。

他の何人かの人たちは天文台がクールだと思うかもしれません。その場合はObservablesを使ってください。これまでのところ、あなたはこれをやっている殺人者ではありません。

No:nonoとno:yesyesはありません。

0
Claudio Ferraro