EventEmitterの適切な使用法は何ですか?


224

ユーザーが自分のサービスでEventEmitterを使用するCustomHttp 内のAccess EventEmitter Serviceのような質問を読みましたが、このコメントで はそれを使用せず、代わりにObservablesを自分のサービスで使用するよう提案されました。

また、この質問を読ん で、ソリューションがEventEmitterを子に渡してサブスクライブすることを提案しています。

私の質問は次のとおりです:EventEmitterを手動でサブスクライブするべきか、それともサブスクライブしないのか?どのように使用すればよいですか?



2
いつものようにマークによる良い答えですが、実際には彼は私が説明した理由を説明していません。私はそれを閉じることに反対ではありませんが、私は彼の意見を最初に求めます。@MarkRajcokの考え?
Eric Martinez

私はこれを開いたままにしたいと思います(そして、私はここで人々を指すと確信しています-私はここで指すように他の回答を編集しました!)。回答には、追加の情報が含まれています。2つの質問のタイトルが欲しいのですが、もう1つは「EventEmitterの適切な使用法は何ですか?」です。
Mark Rajcok 2016年

@MarkRajcok私はそのタイトルが好きですが、現在の回答に適合しないので、後で必ず更新し、使用方法の例と使用しない例を追加して、より意味のあるものにします。ご意見ありがとうございます:)
Eric Martinez

@MarkRajcokは提案されたとおりに編集されました(y)(提案されたタイトルをコピーして貼り付け、すべてのクレジットをあなたに付与します)。
Eric Martinez

回答:


342

TL; DR

いいえ、手動でサブスクライブしたり、サービスで使用したりしないでください。ドキュメントに示されているようにそれらを使用して、コンポーネントでイベントを発行します。Angularの抽象化を無効にしないでください。

回答:

いいえ、手動でサブスクライブしないでください。

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

[...] EventEmitterは実際にはAngularの抽象概念であり、コンポーネントでカスタムイベントを発行する場合にのみ使用する必要があります。それ以外の場合は、Rxを他のライブラリと同じように使用します。

これは、EventEmitterのドキュメントで本当に明確に述べられています。

ディレクティブとコンポーネントで使用して、カスタムイベントを発行します。

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

Angular2は、EventEmitterが引き続きObservableであることを保証しません。つまり、コードが変更された場合にコードをリファクタリングすることです。アクセスする必要がある唯一のAPIはそのemit()メソッドです。EventEmitterを手動でサブスクライブしないでください。

上記のすべては、このワードベルのコメントでより明確です(記事とそのコメントへの回答を読むことをお勧めします)。参考のために引用

EventEmitterが引き続き監視可能であることを期待しないでください!

これらのObservableオペレーターが将来そこにいると期待しないでください!

これらは間もなく非推奨となり、リリース前に削除される可能性があります。

子コンポーネントと親コンポーネント間のイベントバインディングにのみ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();
}

すぐに止めて...あなたはすでに間違っています...

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


1
directives : [Child]コンポーネント定義ではどういう意味ですか?これはコンパイルされていないようで、Angular2のドキュメントに記載されていません。
themathmagician 2016年

1
@エリック:あなたの例でそれを使用しない方法は非常に明白です、なぜサービスで '@Output'デコレータが必要なのですか?
trungk18 2017年

1
@themathmagician少し調べところ、このdirectivesキーワードは廃止されていることがわかりましここまたはここで指示されているdeclarations@NgModule
とおりに

5
Tobyのより最近の回答についてのコメントはありますか?彼の答えは今日受け入れられるべきだと思います。
アルジャン

7
@Ericこの回答を書いたとき、あなたは次のように書いた。しかし、これは2年前に述べられ、現在は角張っています6。この声明は今も当てはまりますか?私は引き続き公式ドキュメントでEventEmitterにsubscribe()メソッドがあることを確認しているので、GoogleがEEをRxjsサブジェクトに基づくのをやめたいのであれば、すでにそれを行っていたと思います。では、元の答えは現在のAngularの状態によく当てはまると思いますか?
Nad G

100

はい、先に進んでそれを使用してください。

EventEmitterある公共、文書タイプ、最終的な角度コアAPIインチ それが基づいているかどうかObservableは関係ありません。その文書化さemitれたsubscribe方法が必要なものに合っている場合は、先に進んでそれを使用してください。

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

Rx.Observableを使用しますが、https//github.com/jhusain/observable-specで指定されているとおりに機能させるためのアダプターを提供します。

仕様のリファレンス実装が利用可能になったら、それに切り替えます。

そのためObservable、特定の方法で動作する同様のオブジェクトが必要だったため、実装して公開しました。それが単に使用されるべきではない内部のAngular抽象化であるなら、彼らはそれを公開しなかっただろう。

特定のタイプのイベントを送信するエミッターがあると便利な場合がたくさんあります。それがあなたのユースケースであるなら、それのために行きます。彼らがリンクしているスペックのリファレンス実装が利用可能な場合は、他のポリフィルと同じように、それはドロップイン置換である必要があります。

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

強く語られた運命と悲観の予測はすべて、Angular 2のプレリリースバージョンに関する単一の開発者からの単一のスタックオーバーフローコメントに由来するようです。


2
これは理にかなっているようです-他の誰かがこれについて検討したいですか?サブスクライブは結局のところ、イベントエミッターのパブリックメソッドですか?
Shawson

わかりました。公開されているので自由に使用できます。しかし、この例でObservableではなくEventEmitterを使用する実用的な理由はありますか?
Botis、2018年

6
現在Angular v6を使用しており、EventEmmiterは廃止または削除されていなかったため、安全に使用できます。ただし、RxJSからObservableを使用する方法を学ぶことにはメリットがあります。
デヴィッド・メザ

「@Outputの外でEventEmitterを使用している場合は、APIが安定したATMであるため、急いで他の何かに変更する必要はありません」と私は思います。時間がある場合、またはAPIが壊れている場合は、変更する必要があります(ただし、angularがpublic stable api(emit and subscribe)を変更することは一般的ではないことに注意してください)。また、公開APIに固執し、EventEmitterで定義されていないSubjectまたはObservableのメソッドにアクセスして、安全側にとどまらないようにしてください
acidghost

1
「Angularから削除されていない」または「十分に文書化されている」ために何かが安全に使用できるという仮定は、上記で提案されたnonoポリシーと同様に間違っています。Angularの将来のバージョンのためではなく、プロジェクトを作成します。まだWebで作業している、外部の多くの非管理型プラットフォームがあります。フレームワークのバージョンは、それらのプラットフォームで作業していた開発者を開発者やBカテゴリの開発者から除外するものではありません。
Claudio Ferraro

4

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

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

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

親子関係でない場合は、サブジェクトを使用するか、共通のサービスを使用する必要があります。


0

no:nooとno:yesyesはありません。真実は真ん中にあり、Angularの次のバージョンのために怖がる理由はありません。

論理的な観点から見ると、コンポーネントがあり、他のコンポーネントに何かが起こったことを通知したい場合、イベントを発生させる必要があります。これは、あなた(開発者)が行うべきだと思う方法で実行できます。どうして使わないのか、どうしても使わないのかわかりません。また、EventEmitterの名前は、イベントの発生を示唆しています。通常、コンポーネントで発生する重要なイベントに使用します。サービスを作成しますが、コンポーネントフォルダー内にサービスファイルを作成します。したがって、私のサービスファイルは一種のイベントマネージャーまたはイベントインターフェイスになるので、現在のコンポーネントでどのイベントにサブスクライブできるかが一目でわかります。

たぶん、私は少し昔ながらの開発者かもしれません。しかし、これはイベント駆動型開発パターンの一部ではなく、特定のプロジェクトのソフトウェアアーキテクチャの決定の一部です。

他の人の中には、Observablesを直接使用するのがクールだと思う人もいます。その場合は、Observablesを直接実行してください。あなたはこれをしている連続殺人犯ではありません。あなたがサイコパスの開発者でない限り、これまでのところプログラムは機能しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.