2016-06-27 업데이트 : Observable을 사용하는 대신 다음 중 하나를 사용하십시오.
- 주석에서 @Abdulrahman이 권장하는 BehaviorSubject
- 댓글에서 @Jason Goemaat가 추천 한 ReplaySubject
주제는 모두 피 감시 (우리가 할 수 있도록 subscribe()
(우리가 호출 할 수 있도록하는 방법)과 옵저버 next()
새 값을 방출하는 데에). 우리는이 기능을 이용합니다. 주체는 값을 많은 관찰자에게 멀티 캐스트 할 수 있습니다. 우리는이 기능을 이용하지 않습니다 (우리는 하나의 관찰자 만 있습니다).
BehaviorSubject 는 Subject의 변형입니다. "현재 값"이라는 개념이 있습니다. ObservingComponent를 만들 때마다 BehaviorSubject에서 현재 탐색 항목 값을 자동으로 가져옵니다.
아래 코드와 플런저 는 BehaviorSubject를 사용합니다.
ReplaySubject 는 Subject의 또 다른 변형입니다. 실제로 값이 생성 될 때까지 기다리려면을 사용하십시오 ReplaySubject(1)
. BehaviorSubject에는 초기 값 (즉시 제공)이 필요하지만 ReplaySubject는 필요하지 않습니다. ReplaySubject는 항상 최신 값을 제공하지만 필요한 초기 값이 없으므로 서비스는 첫 번째 값을 반환하기 전에 비동기 작업을 수행 할 수 있습니다. 가장 최근 값을 가진 후속 통화에서 즉시 실행됩니다. 하나의 값만 원하면 first()
구독 에서 사용 하십시오. 를 사용하는 경우 구독을 취소 할 필요가 없습니다 first()
.
import {Injectable} from '@angular/core'
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Injectable()
export class NavService {
// Observable navItem source
private _navItemSource = new BehaviorSubject<number>(0);
// Observable navItem stream
navItem$ = this._navItemSource.asObservable();
// service command
changeNav(number) {
this._navItemSource.next(number);
}
}
import {Component} from '@angular/core';
import {NavService} from './nav.service';
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number;
subscription:Subscription;
constructor(private _navService:NavService) {}
ngOnInit() {
this.subscription = this._navService.navItem$
.subscribe(item => this.item = item)
}
ngOnDestroy() {
// prevent memory leak when component is destroyed
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.changeNav(item);
}
}
Plunker
Observable을 사용하는 원래 답변 : (BehaviorSubject를 사용하는 것보다 더 많은 코드와 논리가 필요하므로 권장하지 않지만 유익 할 수 있습니다)
여기 EventEmitter 대신 Observable을 사용하는 구현이 있습니다. 내 EventEmitter 구현과 달리이 구현은 현재 navItem
서비스에서 선택된 서비스를 저장 하므로 관찰 컴포넌트가 작성 될 때 API 호출을 통해 현재 값을 검색 navItem()
한 후 navChange$
Observable을 통해 변경 사항을 통지 할 수 있습니다 .
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/share';
import {Observer} from 'rxjs/Observer';
export class NavService {
private _navItem = 0;
navChange$: Observable<number>;
private _observer: Observer;
constructor() {
this.navChange$ = new Observable(observer =>
this._observer = observer).share();
// share() allows multiple subscribers
}
changeNav(number) {
this._navItem = number;
this._observer.next(number);
}
navItem() {
return this._navItem;
}
}
@Component({
selector: 'obs-comp',
template: `obs component, item: {{item}}`
})
export class ObservingComponent {
item: number;
subscription: any;
constructor(private _navService:NavService) {}
ngOnInit() {
this.item = this._navService.navItem();
this.subscription = this._navService.navChange$.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:number;
constructor(private _navService:NavService) {}
selectedNavItem(item: number) {
console.log('selected nav item ' + item);
this._navService.changeNav(item);
}
}
Plunker
옵저버 블 과 함께를 사용하는 Component Interaction Cookbook 예제 도 참조하십시오 Subject
. 예제는 "부모 및 자식 통신"이지만 관련없는 구성 요소에 동일한 기술을 적용 할 수 있습니다.