답변:
BehaviorSubject 는 주제 유형이며 주제는 특수한 유형의 관찰 가능하므로 다른 관찰 가능과 같은 메시지를 구독 할 수 있습니다. BehaviorSubject의 고유 한 기능은 다음과 같습니다.
next()
onnext
getValue()
메소드를 사용하여 관찰 할 수없는 코드로 주제의 마지막 값을 검색 할 수 있습니다 .관찰 가능한 대상과 비교 한 대상의 고유 한 특징은 다음과 같습니다.
또한의 asObservable()
메소드를 사용하여 동작 주제에서 관찰 가능 항목을 얻을 수 있습니다 BehaviorSubject
.
Observable 은 Generic이고 BehaviorSubject
BehaviorSubject는 특정 품질을 가진 Observable이므로 기술적으로 Observable의 하위 유형입니다.
BehaviorSubject를 사용한 예 :
// Behavior Subject
// a is an initial value. if there is a subscription
// after this, it would get "a" value immediately
let bSubject = new BehaviorSubject("a");
bSubject.next("b");
bSubject.subscribe(value => {
console.log("Subscription got", value); // Subscription got b,
// ^ This would not happen
// for a generic observable
// or generic subject by default
});
bSubject.next("c"); // Subscription got c
bSubject.next("d"); // Subscription got d
규칙적인 주제를 가진 예 2 :
// Regular Subject
let subject = new Subject();
subject.next("b");
subject.subscribe(value => {
console.log("Subscription got", value); // Subscription wont get
// anything at this point
});
subject.next("c"); // Subscription got c
subject.next("d"); // Subscription got d
관측은 모두 만들 수 있습니다 Subject
및 BehaviorSubject
사용 subject.asObservable()
.
유일한 차이점은 next()
메소드를 사용하여 관찰 가능 값으로 값을 보낼 수 없다는 것입니다.
Angular 서비스에서는 BehaviorSubject
구성 요소 및 동작 주체가 구성 요소 가이 데이터에 가입 한 이후 새로운 업데이트가 없어도 서비스를 소비하는 구성 요소가 마지막 업데이트 된 데이터를 수신하기 전에 각도 서비스가 종종 초기화되기 때문에 데이터 서비스에 사용하려고합니다.
하나의 매우 중요한 차이점. Observable은 단순한 함수이므로 상태가 없으므로 모든 새로운 Observer에 대해 Observable 작성 코드를 반복해서 실행합니다. 결과 :
코드는 각 관찰자에 대해 실행됩니다. HTTP 호출 인 경우 각 관찰자에 대해 호출됩니다.
이로 인해 주요 버그와 비효율이 발생합니다
BehaviorSubject (또는 Subject)는 관찰자 세부 정보를 저장하고 코드를 한 번만 실행하며 결과를 모든 관찰자에게 제공합니다.
전의:
JSBin : http://jsbin.com/qowulet/edit?js, 콘솔
// --- Observable ---
let randomNumGenerator1 = Rx.Observable.create(observer => {
observer.next(Math.random());
});
let observer1 = randomNumGenerator1
.subscribe(num => console.log('observer 1: '+ num));
let observer2 = randomNumGenerator1
.subscribe(num => console.log('observer 2: '+ num));
// ------ BehaviorSubject/ Subject
let randomNumGenerator2 = new Rx.BehaviorSubject(0);
randomNumGenerator2.next(Math.random());
let observer1Subject = randomNumGenerator2
.subscribe(num=> console.log('observer subject 1: '+ num));
let observer2Subject = randomNumGenerator2
.subscribe(num=> console.log('observer subject 2: '+ num));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.min.js"></script>
출력 :
"observer 1: 0.7184075243594013"
"observer 2: 0.41271850211336103"
"observer subject 1: 0.8034263165479893"
"observer subject 2: 0.8034263165479893"
Observable.create
각 관찰자에 대해 다른 출력을 사용하는 방법을 관찰 하지만 BehaviorSubject
모든 관찰자에 대해 동일한 출력을 제공했습니다. 이것은 중요합니다.
다른 차이점이 요약되어 있습니다.
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Observable ┃ BehaviorSubject/Subject ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Is just a function, no state ┃ Has state. Stores data in memory ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Code run for each observer ┃ Same code run ┃
┃ ┃ only once for all observers ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Creates only Observable ┃Can create and also listen Observable┃
┃ ( data producer alone ) ┃ ( data producer and consumer ) ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Usage: Simple Observable with only ┃ Usage: ┃
┃ one Obeserver. ┃ * Store data and modify frequently ┃
┃ ┃ * Multiple observers listen to data ┃
┃ ┃ * Proxy between Observable and ┃
┃ ┃ Observer ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
KnockoutJS's ko.observable()
더 많은 유사점을 즉시 보게 Rx.BehaviorSubject
됩니다.Rx.Observable
관찰 가능 하고 주제 모두 관찰자가 그들을 추적 할 수 있습니다 관찰의 수단이다. 그러나 둘 다 독특한 특성을 가지고 있습니다. 또한 총 3 가지 유형의 주제가 있으며, 각각의 주제에는 고유 한 특징이 있습니다. 그들 각각을 이해하려고 노력하십시오.
stackblitz 에서 실제 예제를 찾을 수 있습니다 . (실제 출력을 보려면 콘솔을 확인해야합니다)
Observables
차갑습니다. 최소한 하나의 관찰자가 있으면 코드가 실행됩니다.
데이터 사본 생성 : Observable은 각 관찰자에 대한 데이터 사본을 생성합니다.
단방향 : 관찰자는 관찰 가능 (원점 / 마스터)에 값을 할당 할 수 없습니다.
Subject
그들은 뜨겁다 : 관찰자가없는 경우에도 코드가 실행되고 가치가 방송됩니다.
데이터 공유 : 모든 관찰자간에 동일한 데이터가 공유됩니다.
양방향 : 관찰자는 관찰 가능 (원점 / 마스터)에 값을 할당 할 수 있습니다.
주제를 사용하는 경우 관찰자를 작성하기 전에 브로드 캐스팅되는 모든 값을 놓치게됩니다. 여기에 Replay Subject 가 온다
ReplaySubject
그들은 뜨겁다 : 관찰자가없는 경우에도 코드가 실행되고 가치가 방송됩니다.
데이터 공유 : 모든 관찰자간에 동일한 데이터가 공유됩니다.
양방향 : 관찰자는 관찰 가능 (원점 / 마스터)에 값을 할당 할 수 있습니다. ...을 더한
메시지 스트림 재생 : 재생 제목을 구독 할 때 브로드 캐스트 된 모든 메시지가 수신됩니다.
주제 및 재생 주제에서는 초기 값을 관찰 가능으로 설정할 수 없습니다. 여기에 행동 주제가 온다
BehaviorSubject
그들은 뜨겁다 : 관찰자가없는 경우에도 코드가 실행되고 가치가 방송됩니다.
데이터 공유 : 모든 관찰자간에 동일한 데이터가 공유됩니다.
양방향 : 관찰자는 관찰 가능 (원점 / 마스터)에 값을 할당 할 수 있습니다. ...을 더한
메시지 스트림 재생 : 재생 제목을 구독 할 때 브로드 캐스트 된 모든 메시지가 수신됩니다.
초기 값을 설정할 수 있습니다 : 관측 값을 기본값으로 초기화 할 수 있습니다.
ReplaySubject
에는 히스토리가 있으며 일련의 (오래된) 값을 브로드 캐스트 / 방출 할 수 있습니다. buffer가 1로 설정된 경우에만 a와 유사하게 작동합니다 BehaviorSubject
.
Observable 객체는 푸시 기반 컬렉션을 나타냅니다.
Observer 및 Observable 인터페이스는 관찰자 디자인 패턴이라고도하는 푸시 기반 알림에 대한 일반화 된 메커니즘을 제공합니다. Observable 객체는 알림을 보내는 객체 (제공자)를 나타냅니다. Observer 객체는 객체를받는 클래스 (관찰자)를 나타냅니다.
Subject 클래스는 Observable과 Observer를 모두 상속합니다. 이는 Observable과 Observable입니다. 주제를 사용하여 모든 관찰자를 구독 한 다음 주제를 백엔드 데이터 소스에 구독 할 수 있습니다.
var subject = new Rx.Subject();
var subscription = subject.subscribe(
function (x) { console.log('onNext: ' + x); },
function (e) { console.log('onError: ' + e.message); },
function () { console.log('onCompleted'); });
subject.onNext(1);
// => onNext: 1
subject.onNext(2);
// => onNext: 2
subject.onCompleted();
// => onCompleted
subscription.dispose();
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md 에 대한 추가 정보
예제에서 볼 수없는 한 가지는 asObservable을 통해 BehaviorSubject를 Observable로 캐스팅하면 구독시 마지막 값을 반환하는 동작을 상속한다는 것입니다.
종종 라이브러리가 필드를 관찰 가능하게 표시하므로 (즉 Angular2의 ActivatedRoute의 매개 변수) 장면 뒤에서 Subject 또는 BehaviorSubject를 사용할 수 있으므로 까다로운 비트입니다. 그들이 사용하는 것은 구독 행위에 영향을 미칩니다.
여기를 참조하십시오 http://jsbin.com/ziquxapubo/edit?html,js,console
let A = new Rx.Subject();
let B = new Rx.BehaviorSubject(0);
A.next(1);
B.next(1);
A.asObservable().subscribe(n => console.log('A', n));
B.asObservable().subscribe(n => console.log('B', n));
A.next(2);
B.next(2);
관찰은 당신이 반면에만 가입 할 수 있습니다 주제 모두 게시하고 구독 당신을 수 있습니다.
따라서 주제를 사용하면 서비스 를 게시자 및 가입자 모두로 사용할 수 있습니다 .
현재로서는 실력이 좋지 Observable
않으므로의 예만 공유하겠습니다 Subject
.
Angular CLI로 더 잘 이해합시다 예제로 . 아래 명령을 실행하십시오 :
npm install -g @angular/cli
ng new angular2-subject
cd angular2-subject
ng serve
내용을 교체 app.component.html
으로 .
<div *ngIf="message">
{{message}}
</div>
<app-home>
</app-home>
명령 ng g c components/home
을 실행하여 홈 구성 요소를 생성하십시오. 내용을 다음 home.component.html
으로 바꾸십시오 .
<input type="text" placeholder="Enter message" #message>
<button type="button" (click)="setMessage(message)" >Send message</button>
#message
여기에 지역 변수가 있습니다. 속성 추가message: string;
받는 사람app.component.ts
의 클래스에 .
이 명령을 실행하십시오 ng g s service/message
. 이것은 서비스를 생성합니다src\app\service\message.service.ts
. 제공 응용 프로그램에이 서비스를 .
로 가져 Subject
옵니다 MessageService
. 주제도 추가하십시오. 최종 코드는 다음과 같습니다.
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MessageService {
public message = new Subject<string>();
setMessage(value: string) {
this.message.next(value); //it is publishing this value to all the subscribers that have already subscribed to this message
}
}
이제이 서비스를 삽입 home.component.ts
하고 인스턴스를 생성자에게 전달하십시오. 이 작업 app.component.ts
도 수행하십시오. #message
서비스 함수에 값을 전달하려면이 서비스 인스턴스를 사용하십시오 setMessage
.
import { Component } from '@angular/core';
import { MessageService } from '../../service/message.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent {
constructor(public messageService:MessageService) { }
setMessage(event) {
console.log(event.value);
this.messageService.setMessage(event.value);
}
}
내부 app.component.ts
에서 다음을 구독 및 구독 취소 (메모리 누수 방지)합니다 Subject
.
import { Component, OnDestroy } from '@angular/core';
import { MessageService } from './service/message.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
message: string;
subscription: Subscription;
constructor(public messageService: MessageService) { }
ngOnInit() {
this.subscription = this.messageService.message.subscribe(
(message) => {
this.message = message;
}
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
그게 다야.
지금, 임의의 값을 입력 내부 #message
로 home.component.html
에 출력한다 {{message}}
안쪽app.component.html
app.component.ts
behaviourService.setName("behaviour");
behaviour.service.ts
private name = new BehaviorSubject("");
getName = this.name.asObservable();`
constructor() {}
setName(data) {
this.name.next(data);
}
custom.component.ts
behaviourService.subscribe(response=>{
console.log(response); //output: behaviour
});
BehaviorSubject 와 Observable : RxJS에는 옵저버와 옵저버 블이 있으며 Rxjs는 데이터 스트림과 함께 사용할 수있는 여러 클래스를 제공하며 그 중 하나는 BehaviorSubject입니다.
Observables : Observables는 시간이 지남에 따라 여러 값의 게으른 모음입니다.
BehaviorSubject : 초기 값이 필요하고 현재 값을 새로운 가입자에게 내 보냅니다.
// RxJS v6+
import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject(123);
//two new subscribers will get initial value => output: 123, 123
subject.subscribe(console.log);
subject.subscribe(console.log);
//two subscribers will get new value => output: 456, 456
subject.next(456);
//new subscriber will get latest value (456) => output: 456
subject.subscribe(console.log);
//all three subscribers will get new value => output: 789, 789, 789
subject.next(789);
// output: 123, 123, 456, 456, 456, 789, 789, 789
Observables 는 물이 흐르는 파이프, 때로는 물이 흐르고 때로는 흐르지 않는 파이프로 생각하십시오 . 어떤 경우에는, 당신은 실제로 항상 물이 파이프를해야합니다, 당신은 항상 아무리 작은 물을 포함하지 않는 특수 파이프를 생성하여이 작업을 수행 할 수 있습니다,이 특별한 파이프를 호출 할 수 있습니다 BehaviorSubject을 하면 될 일 경우, 지역의 수도 공급 업체 인 경우 새로 설치된 파이프가 제대로 작동한다는 것을 알고 밤에 평화롭게 잠을 잘 수 있습니다.
기술 용어로 : Observable에 항상 가치가 있어야하는 유스 케이스가 발생할 수 있습니다. 시간이 지남에 따라 입력 텍스트의 값을 캡처하려는 경우 BehaviorSubject 인스턴스를 작성하여 이러한 종류의 동작을 보장 할 수 있습니다.
const firstNameChanges = new BehaviorSubject("<empty>");
// pass value changes.
firstNameChanges.next("Jon");
firstNameChanges.next("Arya");
그런 다음 "value"를 사용하여 시간에 따른 변경 사항을 샘플링 할 수 있습니다.
firstNameChanges.value;
이것은 Observable을 나중에 결합 할 때 BehaviorSubject로 스트림 유형을 살펴보면 스트림이 최소한 한 번 이상 실행되거나 신호를 보내 도록 할 수 있습니다 .