주제 vs 행동 주제 vs ReplaySubject in Angular


124

나는 그 3을 이해하기 위해 찾고 있었다.

주제 , 행동 주제재생 주제 . 나는 그것들을 사용하고 싶고 언제, 왜 그것들을 사용하는 것의 이점이 무엇인지 알고 싶습니다. 그리고 문서를 읽었고, 튜토리얼을보고, 구글을 검색했지만 나는 이것을 이해하지 못했습니다.

그래서 그들의 목적은 무엇입니까? 실제 사례는 코딩조차 할 필요가없는 것이 가장 좋을 것입니다.

나는 "a + b => c 당신이 구독하고있는 ...."뿐만 아니라 명확한 설명을 선호합니다.

감사합니다


1
관찰 가능한 행동 주제에 대한 질문이 이미 있습니다. stackoverflow.com/questions/39494058/… 및 재생 주제에 대한 문서는 분명합니다. imo github.com/Reactive-Extensions/RxJS/blob/master/doc/api/…
eko

답변 에는 Rxjs의 주제에 대한 상대적으로 철저한 프레젠테이션이 있으며 , 이는 peeksilet의 답변을 훌륭하게 보완합니다. 여기에는 종료 후 동작에 대한 중요한 세부 정보도 포함되므로 살펴 보는 것이 좋습니다.
user3743222

답변:


278

그것은 실제로 행동과 의미론으로 귀결됩니다. 와 함께

  • Subject-구독자는 구독 후 내 보낸 게시 된 값만받습니다 . 스스로에게 물어보십시오. 구독자가 이전 값에 대해 알아야하는 것이 있습니까? 그렇지 않으면 이것을 사용할 수 있고 그렇지 않으면 다른 하나를 선택할 수 있습니다. 예를 들어 구성 요소 간 통신이 있습니다. 버튼 클릭시 다른 구성 요소에 대한 이벤트를 게시하는 구성 요소가 있다고 가정합니다. 주체가있는 서비스를 이용하여 소통 할 수 있습니다.

  • BehaviorSubject-마지막 값이 캐시됩니다. 구독자는 최초 구독시 최신 가치를 받게됩니다. 이 주제의 의미는 시간이 지남에 따라 변경되는 값을 나타내는 것입니다. 예를 들어 로그인 한 사용자입니다. 초기 사용자는 익명 사용자 일 수 있습니다. 그러나 사용자가 로그인하면 새 값은 인증 된 사용자 상태입니다.

    BehaviorSubject초기 값으로 초기화된다. 이것은 때때로 코딩 선호도에 중요합니다. 예를 들어 null. 그런 다음 구독에서 null 확인을 수행해야합니다. 괜찮을 수도 있고 짜증날 수도 있습니다.

  • ReplaySubject-지정된 배출량까지 캐시 할 수 있습니다. 모든 구독자는 구독시 모든 캐시 된 값을받습니다. 이 동작이 언제 필요합니까? 솔직히 다음과 같은 경우를 제외하고는 그러한 행동이 필요하지 않았습니다.

    당신이를 초기화하는 경우 ReplaySubject의 버퍼 크기 1, 그것은 실제로 작동 단지처럼 BehaviorSubject. 마지막 값은 항상 캐시되므로 시간이 지남에 따라 변경되는 값처럼 작동합니다. 이것으로 초기화 된 null경우와 같이 검사 할 필요가 없습니다 . 이 경우 처음 게시 할 때까지 구독자에게 값이 생성되지 않습니다.BehaviorSubjectnull

그래서 그것은 실제로 당신이 기대하는 행동에 달려 있습니다 (어떤 것을 사용할 것인지). 대부분의 경우 a를 사용하고 싶을 것입니다. BehaviorSubject실제로 표현하려는 것은 "시간 경과에 따른 값"의미 체계이기 때문입니다. 그러나 나는 개인적으로 ReplaySubjectinitialized with 1.

피하고 싶은 Subject것은 정말로 필요한 것이 캐싱 동작 일 때 바닐라를 사용하는 것입니다. 예를 들어 라우팅 가드 또는 해결을 작성하고 있습니다. 그 가드에서 일부 데이터를 가져 와서 서비스에 설정합니다 Subject. 그런 다음 라우팅 된 구성 요소에서 가드에서 내 보낸 값을 가져 오기 위해 서비스 주체에 가입합니다. OOP. 가치는 어디에 있습니까? 이미 방출되었습니다, DUH. "캐싱"주제를 사용하십시오!

또한보십시오:


1
이것은 짧고 차이점을 이해하기 쉽습니다. 서비스에서 값이 변경되고 구성 요소도 값이 표시되도록 변경하면 BehaviourSubjects 또는 Replay Subject가 솔루션입니다.
Saiyaff Farouk

1
감사합니다! ReplaySubject버퍼 크기가 1 인 것이 정확히 필요한 것입니다. 나는 가치가 필요한 경로 경비원이 있었지만 첫 번째 방출을 기다려야했습니다. 소위 BehaviorSubject내가 초기 값을 원하지 않았다으로 (그것을 절단되지 않았다 null내가 상태를 의미하는 데 사용 되었기 때문에 중 하나가 작동하지 않을)
menehune23

1
@ menehune23 Angular resolve가드 클래스 에도 ReplaySubject가 필요했습니다 . 내 데이터 서비스는 비동기 또는 동기 (데이터가 이미 검색된 경우) 일 수 있습니다. 동기식 인 경우 resolve함수가 반환되고 Angular가 내부적으로 구독 하기 전에 Subject.next ()가 실행 되었습니다. BehaviourSubject는 작동 할 수 있지만 명시 적으로 호출 complete()하고 null초기 값에 대한 검사를 추가해야 합니다. 어떤 일을하는 것은 새로웠다 ReplaySubject<DataType>(1)resolveSubject.asObservable().take(1).map(....)
Drenai

1
버퍼 크기가 1 인 ReplaySubject를 사용하고 있지만 어떤 이유로 Observable이 .asObservable()있는 Observable을 얻으면 ReplaySubject를 null호출하기 전에 구독자에게 값을 next()보냅니다. BehaviorSubject와는 달리 초기 값이 있으면 안된다고 생각 했나요?
Kyle V.

2
재생 주제에 대해 언급 할 수있는 매우 쉬운 예는 새로운 참여자가 최근 10 개의 메시지를 보길 원하는 "채팅"또는 게임 로비 시나리오에 대한 것입니다.
James

16

다양한 관찰 가능한 유형, 직관적이지 않은 이름 지정에 대한 편리한 요약입니다 .

  • Subject -구독자는 구독이 이루어진 후에 만 ​​게시 된 값을 받게됩니다.
  • BehaviorSubject -신규 구독자는 구독 즉시 마지막으로 게시 된 값 또는 초기 값을받습니다.
  • ReplaySubject -신규 구독자는 구독 즉시 이전에 게시 된 모든 가치를 얻습니다.

1-n 게시 된 값? 따라서 2 개의 게시 된 값이있는 경우 ReplaySubject는 -1 개의 게시 된 값을 생성합니다. ???
Jason Cheng

@JasonCheng 아니요 구독시 이전에 게시 된 모든 값을 검색하고 답변을 업데이트합니다. :)
Ricky Boyce

11
  1. 제목 : 구독시 항상 구독 후 푸시 된 데이터를 가져옵니다. 즉, 이전 푸시 된 값이 수신되지 않습니다 .
const mySubject = new Rx.Subject();

mySubject.next(1);

const subscription1 = mySubject.subscribe(x => {
  console.log('From subscription 1:', x);
});

mySubject.next(2);

const subscription2 = mySubject.subscribe(x => {
  console.log('From subscription 2:', x);
});

mySubject.next(3);

subscription1.unsubscribe();

mySubject.next(4);

이 예에서 콘솔에 인쇄 될 결과는 다음과 같습니다.

From subscription 1: 2
From subscription 1: 3
From subscription 2: 3
From subscription 2: 4

늦게 도착하는 구독이 주제로 푸시 된 일부 데이터에서 어떻게 누락되는지 확인하십시오.

  1. Replay subjects : 새 구독으로 내보낼 이전 값버퍼를 유지하여 도움을 줄 수 있습니다 .

다음 buffer of 2 previous values은 a 가 새 구독에서 유지되고 내보내 지는 재생 주제의 사용 예입니다 .

const mySubject = new Rx.ReplaySubject(2);

mySubject.next(1);
mySubject.next(2);
mySubject.next(3);
mySubject.next(4);

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

콘솔에서 제공하는 내용은 다음과 같습니다.

From 1st sub: 3
From 1st sub: 4
From 1st sub: 5
From 2nd sub: 4
From 2nd sub: 5
  1. 행동 주제 : 재생 주제와 유사하지만 마지막으로 내 보낸 값만 다시 내 보냅니다. 이전에 내 보낸 값이없는 경우 기본값을 다시 내 보냅니다.
const mySubject = new Rx.BehaviorSubject('Hey now!');

mySubject.subscribe(x => {
  console.log('From 1st sub:', x);
});

mySubject.next(5);

mySubject.subscribe(x => {
  console.log('From 2nd sub:', x);
});

그 결과 :

From 1st sub: Hey now!
From 1st sub: 5
From 2nd sub: 5

참조 : https://alligator.io/rxjs/subjects/


4

출처 : Randall Koutnik 책“RxJS로 반응 형 웹 사이트 구축” :

주제는 A가 관찰 터보 차저의 개체입니다. 핵심에서 주제 는 일반 관찰 가능 항목과 매우 유사하게 작동하지만 각 구독은 동일한 소스에 연결됩니다. 주제 는 또한 관찰자이며 모든 구독자에게 한 번에 데이터를 전송하는 next, error 및 done 메소드가 있습니다. 주체 는 옵저버 이기 때문에 구독 호출로 직접 전달 될 수 있으며 원래 옵저버 블의 모든 이벤트는 주체를 통해 구독자에게 전송됩니다.

ReplaySubject 를 사용하여 기록 을 추적 할 수 있습니다 . ReplaySubject는 그들에게 모든 새로운 가입자에게 다시 마지막 n 이벤트 및 palys를 기록합니다. 예를 들어 채팅 응용 프로그램에서. 이전 채팅 기록을 추적하는 데 사용할 수 있습니다.

BehaviorSubject는 의 단순화 된 버전입니다 ReplaySubject . ReplaySubject 이벤트의 임의의 수를 저장은 BehaviorSubject은 최신 이벤트의 값을 기록합니다. BehaviorSubject 가 새 구독을 기록 할 때마다 구독자에게 최신 값과 전달 된 새 값을 내 보냅니다 . BehaviorSubject 는 구성 옵션과 같은 단일 상태 단위를 처리 할 때 유용합니다.


1

대부분의 찬성 답변은 다음과 같이 주장하는 것이 명백히 잘못되었습니다.

" ReplaySubject버퍼 크기가 1 인 a 를 초기화 하면 실제로는 BehaviorSubject"


이것은 완전히 사실이 아닙니다. 둘의 차이점에 대한 훌륭한 블로그 게시물 을 확인하십시오 . 예를 들어 완료된에 가입 BehaviorSubject하면 마지막 값을받지 못하지만에 대한 마지막 값 ReplaySubject(1)을 받게됩니다.

이것은 간과해서는 안되는 중요한 차이점입니다.

const behavior = new BehaviorSubject(null);
const replay = new ReplaySubject(1);

behavior.skip(1).subscribe(v => console.log('BehaviorSubject:', v));
replay.subscribe(v => console.log('ReplaySubject:', v));

behavior.next(1);
behavior.next(2);
behavior.complete();
behavior.subscribe(v => console.log('Late B subscriber:', v));

replay.next(1);
replay.next(2);
replay.complete();
replay.subscribe(v => console.log('Late R subscriber:', v));

주제에 대한 또 다른 훌륭한 블로그 게시물 에서 가져온 이 코드 예제를 여기에서 확인하십시오 .


0
     // ***********Subject  concept ***********
    let subject = new Subject<string>();


    subject.next("Eureka");
    subject.subscribe((data) => {
      console.log("Subscriber 1 got data >>>>> "+ data);
    });
    subject.subscribe((data) => {
      console.log("Subscriber 2 got data >>>>> "+ data);
    });

       // ********behaviour subject*********
    // Behavior subjects need a first value
let subject1 = new BehaviorSubject<string>("First value");


subject1.asObservable().subscribe((data) => {
  console.log("First subscriber got data behaviour subject>>>>> "+ data);
});
subject1.next("Second value")
  • 제목-구독자는 구독이 이루어진 후에 만 ​​게시 된 값을받습니다.
  • BehaviorSubject-신규 구독자는 구독 즉시 마지막으로 게시 된 값 또는 초기 값을받습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.