Angular2의 서비스 이벤트를 구독하는 방법은 무엇입니까?


112

EventEmitter로 이벤트를 발생시키는 방법을 알고 있습니다. 다음과 같은 구성 요소가있는 경우 호출 할 메서드를 연결할 수도 있습니다.

<component-with-event (myevent)="mymethod($event)" />

이와 같은 구성 요소가 있으면 모든 것이 잘 작동합니다. 일부 로직을 서비스로 이동했고 서비스 내부에서 이벤트를 발생시켜야합니다. 내가 한 일은 다음과 같습니다.

export class MyService {
  myevent: EventEmitter = new EventEmitter();

  someMethodThatWillRaiseEvent() {
    this.myevent.next({data: 'fun'});
  }
}

이 이벤트를 기반으로 일부 값을 업데이트해야하는 구성 요소가 있지만 제대로 작동하지 않는 것 같습니다. 내가 시도한 것은 다음과 같습니다.

//Annotations...
export class MyComponent {
  constructor(myService: MyService) {
    //myService is injected properly and i already use methods/shared data on this.
    myService.myevent.on(... // 'on' is not a method <-- not working
    myService.myevent.subscribe(.. // subscribe is not a method <-- not working
  }
}

이벤트를 발생시키는 서비스가 컴포넌트가 아닌 경우 MyComponent가 이벤트를 구독하게하려면 어떻게해야합니까?

2.0.0-alpha.28에 있습니다.

편집 : 실제로 작동하도록 내 "작동 예제"를 수정하여 작동하지 않는 부분에 초점을 맞출 수 있습니다.)

예제 코드 : http://plnkr.co/edit/m1x62WoCHpKtx0uLNsIv


1
서비스를 구성 요소에 단단히 연결하기 때문에 서비스가 구성 요소를 대신하여 이벤트를 내 보내지 않아야하는 디자인 문제 일 수 있습니다. 예를 들어 구성 요소의 인스턴스가 여러 개있는 경우 모두 이벤트를 내 보내야합니까?
Angular University

@jhadesdev 나는 당신을 읽었습니다. 서비스가 더 이상 결과를 내보낼 필요가 없도록 솔루션을 재 설계했습니다. 어떤 종류의 "서비스"그것이 ...의 따라 - 나는 아직도 약간의 디자인이 인상 이벤트에 수있는에서 bennefit 것이라고 생각
당 Hornshøj-Schierbeck을

한 가지 방법은 다음 구성 요소가 대신 서비스의 이벤트 이미 터를 생성하도록 할 수 있으며, 다음 서비스에 대한 인수로 이벤트 이미 터를 전달
각도 대학

답변:


135

업데이트 : EventEmitter가 아닌 BehaviorSubject 또는 Observable을 사용하여이 문제를 해결하는 더 나은 / 적절한 방법을 찾았습니다. 이 답변을 참조하십시오 : https://stackoverflow.com/a/35568924/215945

또한 Angular 문서에는 이제 Subject를 사용하는 요리 책 예제가 있습니다.


원래 / 오래된 / 오답 : 다시 말하지만 서비스에서 EventEmitter를 사용하지 마십시오 . 그것은 반 패턴입니다.

beta.1 사용 중 ... NavService에는 EventEmiter가 포함되어 있습니다. 구성 요소 탐색은 서비스를 통해 이벤트를 내보내고 구성 요소 ObservingComponent는 이벤트를 구독합니다.

nav.service.ts

import {EventEmitter} from 'angular2/core';
export class NavService {
  navchange: EventEmitter<number> = new EventEmitter();
  constructor() {}
  emitNavChangeEvent(number) {
    this.navchange.emit(number);
  }
  getNavChangeEmitter() {
    return this.navchange;
  }
}

components.ts

import {Component} from 'angular2/core';
import {NavService} from '../services/NavService';

@Component({
  selector: 'obs-comp',
  template: `obs component, item: {{item}}`
})
export class ObservingComponent {
  item: number = 0;
  subscription: any;
  constructor(private navService:NavService) {}
  ngOnInit() {
    this.subscription = this.navService.getNavChangeEmitter()
      .subscribe(item => this.selectedNavItem(item));
  }
  selectedNavItem(item: number) {
    this.item = item;
  }
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'my-nav',
  template:`
    <div class="nav-item" (click)="selectedNavItem(1)">nav 1 (click me)</div>
    <div class="nav-item" (click)="selectedNavItem(2)">nav 2 (click me)</div>
  `,
})
export class Navigation {
  item = 1;
  constructor(private navService:NavService) {}
  selectedNavItem(item: number) {
    console.log('selected nav item ' + item);
    this.navService.emitNavChangeEvent(item);
  }
}

Plunker


나는 이것을 따랐지만 수업 자체에서만 작동합니다. 다른 클래스에서 작동하지 않습니다 (다른 파일에서). 문제가 서비스 클래스 인스턴스에있는 것 같습니다. 어쨌든 서비스 클래스를 정적으로 만들 수 있습니까?
asubanovsky

5
@asubanovsky의에서 plunker 부트 스트랩에서만 NavService 분사 I (즉, 루트 구성 요소) 수준, 그래서 단지 전체 응용 프로그램에 대한 서비스의 인스턴스가 있어야합니다. 다른 곳에 주사하고 providers: [NavService]있습니까? 그렇다면 서비스의 여러 인스턴스를 얻게됩니다.
Mark Rajcok

대단히 감사합니다. 이제 내 기대대로 작동하고 있습니다. 이제 부트 스트랩 수준과 구성 요소 수준에서 공급자를 주입하는 것의 차이점을 이해했습니다.
asubanovsky

이 게시물은 더 이상 '얻지'않는 상태로 심각하게 변경되었습니다. navChange를 직접 구독하는 것과 다른 EventEmitter를 반환하는 .getNavChangeEmitter () 서비스에서 mehtod를 호출하는 이유는 무엇입니까?
Per Hornshøj-Schierbeck

@ PerHornshøj-Schierbeck, getNavChangeEmitter () 메서드를 사용하여 EventEmitter가 서비스 내부에서 사용되고 있다는 사실을 숨겼습니다. 메서드 사용자는 반환 된 개체에 메서드가 있다고 가정 할 수 subscribe()있습니다. 메서드를 사용하면 EventEmitter를 Subject 또는 Observable로 쉽게 변경할 수 있습니다. 이제 EventEmitters는 Output 속성에만 사용해야한다는 것을 배웠기 때문에 훨씬 좋습니다. 적절한 방법은 Subject, BehaviorSubject 또는 Observable을 사용하는 것입니다. 우리는 보통 이것들을 직접 구독하므로 더 이상 getNavChangeEmitter () 메소드가 필요하지 않습니다.
Mark Rajcok

6

알파 28을 사용하여 eventEmitter.toRx().subscribe(..)메서드 를 통해 이벤트 이미 터를 프로그래밍 방식으로 구독했습니다 . 직관적이지 않기 때문에 향후 릴리스에서 변경 될 수 있습니다.


1
사람들이이 게시물을 우연히 발견 할 때 사용할 수있는 간단한 예를 제공 할 수 있습니까? 그것은 나 BTW downvoting되지 않았습니다)
당 Hornshøj-Schierbeck을

2
왜 반대표를 받았는지 모르겠지만 확실히 작동합니다. 간단히 말해서 이벤트 이미 터 "클릭"을 구독하려면 다음을 사용하십시오. click.toRx().subscribe(your_callback_function)
Runeboy

작동하는 예가 없기 때문에 비추천을 받았을 수도 있습니다. 나는 그것이 pluncker / jsfiddle 바이올린에 대한 링크 또는 구문을 더 잘 표시하기위한 코드 줄이 있다면 찬성 할 가치가있을 것이고 아마도 받아 들여질만한 대답 일 것임을 압니다;)
Per Hornshøj-Schierbeck

예외 : ReferenceError : 클릭이 정의되지 않았습니다. @Runeboy 솔루션에 대한 plnkr을 제공 할 수 있습니까?
Benjamin McFerren 2015

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