EventEmitter의 올바른 사용법은 무엇입니까?


225

사용자가 자신의 서비스에서 EventEmitter를 사용하는 CustomHttp 내부의 Access EventEmitter Service 와 같은 질문을 읽었 지만이 의견 에서는 사용하지 말고 대신 서비스에서 직접 Observables를 사용하도록 제안했습니다 .

또한 솔루션이 EventEmitter를 자식에게 전달하고 구독하도록 제안하는 이 질문 을 읽었 습니다.

내 질문은 다음과 같습니다. EventEmitter를 수동으로 구독해야합니까? 어떻게 사용해야합니까?



2
평소와 같이 Mark의 좋은 대답이지만 실제로는 내가 왜 설명했는지 설명하지 않습니다. 나는 그것을 닫는 것에 반대하지 않지만 먼저 그의 의견을 원한다. @MarkRajcok 생각?
Eric Martinez

나는 이것을 열어두고 싶습니다 (그리고 여기 사람들을 가리킬 것이라고 확신합니다-여기에서 다른 대답을 편집했습니다!). 귀하의 답변에는 약간의 추가 정보가 있습니다. 그래도 두 개의 질문 제목이 필요합니다. 다른 하나는 "EventEmitter의 올바른 사용법은 무엇입니까?"
Mark Rajcok

@MarkRajcok 나는 그 제목을 좋아하지만 현재 답변과 맞지 않을 것이므로 나중에 업데이트하고 사용 방법과 사용하지 않는 방법에 대한 예제를 추가하여 더 이해하기 쉽게 만들 것입니다. 의견 주셔서 감사합니다 :)
Eric Martinez

@MarkRajcok은 제안 된대로 편집 했음 (y), (제목 된 제목, 모든 크레딧을 복사하여 붙여 넣기)
Eric Martinez

답변:


342

TL; DR :

아니요, 수동으로 구독하지 말고 서비스에서 사용하지 마십시오. 구성 요소에서 이벤트를 생성하려면 문서에 표시된대로 사용하십시오. 각도의 추상화를 물리 치지 마십시오.

대답:

아니요, 수동으로 구독하면 안됩니다.

EventEmitter 는 각도 2 추상화이며 유일한 목적은 구성 요소에서 이벤트를 생성하는 것입니다. Rob Wormald 의 의견 인용

[...] EventEmitter는 실제로 앵귤러 추상화이며, 컴포넌트에서 커스텀 이벤트를 생성하는 경우에만 사용되어야합니다. 그렇지 않으면 Rx를 다른 라이브러리처럼 사용하십시오.

이것은 EventEmitter의 문서에서 실제로 명확하게 설명되어 있습니다.

지시문 및 구성 요소에서 사용하여 사용자 정의 이벤트를 생성합니다.

사용에있어 무엇이 문제입니까?

Angular2는 EventEmitter가 계속 Observable임을 보장하지 않습니다. 따라서 코드가 변경되면 코드를 리팩토링해야합니다. 우리가 액세스해야하는 유일한 API는 emit()메소드입니다. EventEmitter를 수동으로 구독해서는 안됩니다.

위에 언급 된 모든 내용은이 Ward Bell의 의견 (기사 및 해당 의견에 대한 답변 을 읽는 것이 좋습니다) 에서 더 명확 합니다. 참조 인용

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

그만해. 넌 이미 틀렸어 ...

이 두 가지 간단한 예제가 EventEmitter의 올바른 사용법을 명확히하기를 바랍니다.


1
directives : [Child]구성 요소 정의에서 무엇을 의미 합니까? 이것은 컴파일되지 않는 것 같으며 Angular2 설명서에 설명되어 있지 않습니다.
themathmagician

1
@Eric : 예제에서 사용하지 않는 방법은 매우 분명합니다. 왜 서비스에 '@Output'데코레이터가 필요한가요?
trungk18

1
@themathmagician 연구의 조금 후에, 나는 발견 여기 있음을 directives키워드부터 사용되지 않습니다. 여기 또는 여기에 지시 declarations@NgModule대로 키워드를 사용 하십시오
cjsimon

5
Toby의 최근 답변에 대한 의견이 있습니까? 요즘 그의 대답은 받아 들여질 것 같아요.
Arjan

7
@Eric이 답변을 썼을 때, Ward Bell을 인용하면서 '이것들은 곧 폐기 될 것이며 출시 전에 제거 될 것입니다. 그러나 이것은 2 년 전에 언급되었으며 지금 우리는 각도 6을 가지고 있습니다. 이 진술이 지금도 계속 적용됩니까? 나는 공식 문서에서 EventEmitter가 여전히 subscribe () 메소드를 가지고 있음을 계속보고 있기 때문에 Google이 Rxjs 주제에 대한 EE의 기초를 멈추고 싶다면 이미 그것을했을 것이라고 생각합니다. 따라서 원래 답변이 여전히 현재 Angular 상태에 잘 맞는다고 생각하십니까?
Nad G

101

예, 계속 사용하십시오.

EventEmitter최종 Angular Core API 의 공개 문서화 된 유형 입니다. 그것이 기반인지 여부 Observable는 관련이 없습니다. 문서화 emit되고 subscribe방법이 필요한 것에 적합하다면 계속 사용하십시오.

문서에 명시된 바와 같이 :

Rx.Observable을 사용하지만 https://github.com/jhusain/observable-spec에 지정된대로 작동하도록 어댑터를 제공합니다.

사양의 참조 구현을 사용할 수있게되면 해당 사양으로 전환하십시오.

그래서 그들은 Observable특정한 방식으로 행동 하는 유사한 물건을 원했고 그것을 구현하고 공개했습니다. 내부 앵귤러 추상화로 사용해서는 안된다면, 공개하지 않았을 것입니다.

특정 유형의 이벤트를 보내는 이미 터를 갖는 것이 유용한 경우가 많습니다. 그것이 당신의 유스 케이스라면 가십시오. 링크 된 스펙의 참조 구현이 사용 가능한 경우 다른 폴리 필과 마찬가지로 드롭 인 대체품이어야합니다.

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
이것은 합리적으로 들립니다-다른 누군가가 이것에 대해 무게를 달기를 원하십니까? subscribe는 결국 이벤트 이미 터에서 공개적인 방법입니까?
Shawson

좋습니다. 공개되어 있으므로 무료로 사용할 수 있습니다. 그러나이 예제에서 EventEmitter over Observable을 사용해야하는 실질적인 이유가 있습니까?
Botis

6
우리는 이제 Angular v6을 사용하고 있으며 EventEmmiter는 더 이상 사용되지 않거나 제거되지 않았으므로 사용하기에 안전하다고 말하고 싶습니다. 그러나 RxJS에서 Observables를 사용하는 방법을 배우면 이점이 있습니다.
David Meza

"@Output 외부에서 EventEmitter를 사용하는 경우 api가 안정적인 ATM이므로 다른 것으로 변경하지 않아도됩니다."; 시간이 있거나 API가 중단되면 변경해야합니다 (그러나 각도가 공개 안정 API를 변경하려면 (방출 및 구독)이 일반적이지 않음을 명심하십시오). 또한, 공개 API에 충실, EventEmitter에 정의되지 않은 주제 또는 관찰 가능한 아닌 접근 방법은 안전 측면에 머물 않습니다
acidghost

1
위에서 제안 된 nono 정책뿐만 아니라 "Angular에서 제거되지 않음"또는 "잘 문서화 됨"때문에 사용하기에 안전한 것으로 가정하는 것은 잘못입니다. 향후 버전의 각도 때문에 프로젝트를 작성하지 않습니다. 외부에는 아직 웹에서 작동하는 비 관리 플랫폼이 많이 있습니다. 프레임 워크의 버전은 해당 플랫폼에서 작업하는 개발자가 개발자 또는 B 범주의 개발자보다 덜 만들지 않습니다.
Claudio Ferraro

4

교차 컴포넌트 상호 작용을 원하면 @Input, @Output, EventEmitter 및 Subjects가 무엇인지 알아야합니다.

컴포넌트 간의 관계가 부모 자식이거나 그 반대 인 경우 @input & @output을 이벤트 이미 터와 함께 사용합니다.

@output은 이벤트를 발생시키고 이벤트 이미 터를 사용하여 방출해야합니다.

부모와 자식 관계가 아닌 경우 주제를 사용하거나 공통 서비스를 통해 사용해야합니다.


0

noo와 no : yesyes가 없습니다. 진실은 중간에 있으며 다음 버전의 Angular 때문에 두려워 할 이유가 없습니다.

논리적 관점에서 볼 때 구성 요소가 있고 다른 구성 요소에 어떤 일이 발생했음을 알리려면 이벤트를 시작해야하며 이는 개발자 (개발자)가 생각한 방식에 따라 수행 될 수 있습니다. 나는 그것을 사용하지 않는 이유를 보지 못하고 모든 비용으로 그것을 사용해야하는 이유를 보지 못합니다. 또한 EventEmitter 이름은 이벤트가 발생했음을 나타냅니다. 나는 보통 컴포넌트에서 일어나는 중요한 이벤트에 사용합니다. 서비스를 만들지 만 구성 요소 폴더 내에 서비스 파일을 만듭니다. 따라서 내 서비스 파일은 일종의 이벤트 관리자 또는 이벤트 인터페이스가되므로 현재 구성 요소에서 구독 할 수있는 이벤트를 한눈에 파악할 수 있습니다.

나는 아마 구식 개발자 일 것이다. 그러나 이것은 이벤트 중심 개발 패턴의 일부가 아니며 특정 프로젝트의 소프트웨어 아키텍처 결정의 일부입니다.

다른 사람들은 Observables를 직접 사용하는 것이 멋지다고 생각할 수도 있습니다. 이 경우 Observables를 직접 진행하십시오. 당신은 이것을하는 연쇄 살인범이 아닙니다. 사이코 패스 개발자가 아니라면 지금까지 프로그램이 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.