Program Tip

고온 및 저온 관측 가능 : '고온'및 '저온'연산자가 있습니까?

programtip 2020. 12. 12. 12:17
반응형

고온 및 저온 관측 가능 : '고온'및 '저온'연산자가 있습니까?


나는 다음과 같은 질문을 검토했다 : 뜨겁고 차가운 관측 물은 무엇인가?

요약:

  • 콜드 옵저버 블은 옵저버가 소비 할 때 그 값을 방출합니다. 즉 옵저버가 수신 한 값의 시퀀스는 구독 시간과 무관합니다. 모든 관찰자는 동일한 일련의 값을 소비합니다.
  • 핫 옵저버 블은 구독과는 독립적으로 가치를 방출합니다. 즉, 옵저버가받은 값은 구독 시간의 함수입니다.

그러나 나는 더위와 추위가 여전히 혼란의 근원이라고 생각합니다. 그래서 여기 내 질문이 있습니다.

  • 모든 rx 관찰 가능 항목은 기본적으로 차갑습니까 (피험자를 제외하고)?

    나는 종종 이벤트가 핫 옵저버 블에 대한 전형적인 은유라는 것을 읽었지만, 그것도 Rx.fromEvent(input, 'click')콜드 옵저버 블 (?) 이라고 읽었습니다 .

  • 콜드 옵저버 블을 핫 옵저버 블로 바꾸는 Rx 연산자가 있습니까 / 무엇입니까 ( publish, 및 제외 share)?

    예를 들어, Rx 연산자와 어떻게 작동 withLatestFrom합니까? 하자 cold$어딘가에에 가입되어있는 감기 관찰을합니다. sth$.withLatestFrom(cold$,...)뜨거운 관찰을 할 수?

    내가 할 경우 또는 sth1$.withLatestFrom(cold$,...), sth2$.withLatestFrom(cold$,...)과에 가입 sth1하고 sth2, 나는 항상 모두에 대해 동일한 값을 볼 수 sth?

  • 나는 Rx.fromEvent콜드 옵저버 블을 생성 한다고 생각 했지만 답변 중 하나에서 언급했듯이 그렇지 않습니다. 그러나 나는 여전히이 행동에 당황스러워합니다 : codepen.io/anon/pen/NqQMJR?editors=101 . 다른 구독은 동일한 Observable에서 다른 값을 얻습니다. click이벤트가 공유 되지 않았습니까 ?


나는 몇 달 후 원래의 질문으로 돌아와 그 동안 얻은 지식을 공유하고 싶었습니다. 설명 지원 ( jsfiddle ) 으로 다음 코드를 사용 하겠습니다 .

var ta_count = document.getElementById('ta_count');
var ta_result = document.getElementById('ta_result');
var threshold = 3;

function emits ( who, who_ ) {return function ( x ) {
  who.innerHTML = [who.innerHTML, who_ + " emits " + JSON.stringify(x)].join("\n");
};}

var messages$ = Rx.Observable.create(function (observer){
  var count= 0;
  setInterval(function(){
    observer.onNext(++count);
  }, 1000)
})
.do(emits(ta_count, 'count'))
.map(function(count){return count < threshold})
.do(emits(ta_result, 'result'))

messages$.subscribe(function(){});

답변 중 하나에서 언급했듯이 관찰 가능 항목을 정의하면 일련의 콜백 및 매개 변수 등록이 발생합니다. 데이터 흐름은 시작되어야하며 subscribe함수 를 통해 수행됩니다 . 이후에 자세한 흐름을 찾을 수 있습니다 (예시를 위해 단순화 됨).

단순화 된 흐름도

Observable은 기본적으로 차갑습니다. Observable을 구독하면 업스트림 구독 체인이 발생합니다. 마지막 구독은 소스를 처리하고 관찰자에게 데이터를 내보내는 함수의 실행으로 이어집니다.

그 관찰자는 차례로 다음 관찰자에게 방출되어 데이터의 다운 스트림 흐름이 싱크 관찰자로 내려갑니다. 다음 단순화 된 그림은 두 구독자가 동일한 관찰 항목을 구독 할 때 구독 및 데이터 흐름을 보여줍니다.

차가운 관찰 가능한 단순화 된 흐름도

핫 옵저버 블은 주제를 사용하거나 multicast연산자 (및 그 파생물, 아래 참고 3 참조)를 통해 생성 할 수 있습니다 .

multicast후드 아래 연산자는 대상을 사용하고 연결 가능한 관찰 대상을 반환합니다. 운영자에 대한 모든 구독은 내부 주제에 대한 구독입니다. 경우 connect라고 내부 피사체 상류 관찰에 가입 한 데이터 하류 흐른다. 주제는 내부적으로 구독 된 관찰자 목록을 조작하고 모든 구독 된 관찰자에게 들어오는 데이터를 멀티 캐스트합니다.

다음 다이어그램은 상황을 요약합니다.

뜨거운 관찰 가능한 단순화 된 흐름도

In the end, it matters more to understand the flow of data caused by the observer pattern and the implementation of the operators.

For instance, if obs is hot, is hotOrCold = obs.op1 cold or hot? Whatever the answer is :

  • if there are no subscribers to obs.op1, no data will flow through op1. If there were subscribers to hot obs, that means obs.op1 will have possibly lost pieces of data
  • supposing that op1 is not a multicast-like operator, subscribing twice to hotOrCold will subscribe twice to op1, and every value from obs will flow twice through op1.

Notes :

  1. This information should be valid for Rxjs v4. While the version 5 has gone through considerable changes, most of it still applies verbatim.
  2. Unsubscription, error and completion flows are not represented, as they are not in the scope of the question. Schedulers are also not taken into account. Among other things, they influence the timing of the data flow, but a priori not its direction and content.
  3. According to the type of subject used for multicasting, there are different derived multicasting operators:

Subject type | `Publish` Operator | `Share` operator ------------------ | --------------------------- | ----------------- Rx.Subject | Rx.Observable.publish | share Rx.BehaviorSubject | Rx.Observable.publishValue | shareValue Rx.AsyncSubject | Rx.Observable.publishLast | N/A Rx.ReplaySubject | Rx.Observable.replay | shareReplay

Update : See also the following articles, here, and there) on that subject by Ben Lesh.

Further details on subjects can be found in this other SO question : What are the semantics of different RxJS subjects?


Your summary, and the linked question are both correct, I think the terminology may be confusing you. I propose you think of hot and cold observables as active and passive observables (respectively).

That is, an active (hot) observable will be emitting items whether someone has subscribed or not. The canonical example, again, button click events happen whether someone is listening to them or not. This distinction is important because, if, for example, I click a button and then subscribe to button clicks (in that order), I will not see the button click that has already happened.

A passive (cold) observable will wait until a subscriber exists before emitting items. Imagine a button where you cannot click on it until someone is listening to the events—this would ensure that you always see each and every click event.

Are all Rx observables "cold" (or passive) by default? No, Rx.fromEvent(input, 'click') for example is a hot (or active) observable.

I also read that Rx.fromEvent(input, 'click') is a cold observable(?)

That is not the case.

Are there Rx operators which turn a cold observable into a hot observable?

The concept of turning a hot (active) observable into a cold (passive) observable is this: you need to record the events that happen while nothing is subscribed and offer those items (in various ways) to subscribers that come along in the future. One way to do this is to use a Subject. For example, you could use a ReplaySubject to buffer up items emitted and replay them to future subscribers.

The two operators you named (publish and share) both use subjects internally to offer that functionality.

How does it work with Rx operator withLatestFrom? Let cold$ be a cold observable which has been subscribed to. Will something$.withLatestFrom(cold$,...) be a hot observable?

If something is a hot observable, then yes. If something is a cold observable, then no. Going back to the events example, if something is a stream of button click events:

var clickWith3 = Rx.fromEvent(input, 'click')
    .withLatest(Rx.Observable.from([1, 2, 3]);

Or if I do foo$.withLatestFrom(cold$,...), bar$.withLatestFrom(cold$,...) and subscribe to foo and bar, will I always see the same values for both?

Not always. Again, if foo and bar are clicks on different buttons for example, then you would see different values. As well, even if they were the same button, if your combination function (the 2nd argument to withLatest) does not return the same result for the same inputs, then you would not see the same values (because it would be called twice, as explained below).

I thought Rx.fromEvent creates cold observables but that is not the case, as mentioned in one of the answers. However, I am still baffled by this behaviour: codepen.io/anon/pen/NqQMJR?editors=101. Different subscriptions get different values from the same observable. Wasn't the click event shared?

I'll point you to this great answer by Enigmativity to a question I had about the same behaviour. That answer will explain it a lot better than I can, but the gist of it is that the source (the click event) is "shared", yes, but your operations on it are not. If you want to share not just the click event but also the operation on it, you will need to do so explicitly.


values in your codepen is lazy - nothing happens until something subscribes, at which point it runs through and wires it up. So in your example, although you are subscribing to the same variable, it is creating two different streams; one for each subscribe call.

You can think of values as being a generator of streams for click with that map attached.

.share() on the end of that map would create the behaviour we expect, because it is implicitly subscribing.


모든 질문에 대한 답은 아니지만 (모두 알고 싶습니다!) 확실히 모든 fromEventObservable이 뜨겁습니다. 클릭은 mousemove와 같은 "연속적인"이벤트가 아니기 때문에 아닌 것으로 보이지만 어쨌든 Observable이 생성 될 때 소스 ( addEventListener또는 on호출) 에 대한 구독 은 한 번만 수행됩니다. 그래서 뜨겁습니다. 당신은 운영자의 소스 코드를 볼 수 있습니다 여기에있다 - 생성 관측은 share이벤트 이름 또는 소스 무엇인지에 상관없이 거라고.

참고 URL : https://stackoverflow.com/questions/32190445/hot-and-cold-observables-are-there-hot-and-cold-operators

반응형