2017-12-04 8 views
1

Wenn ich eine gemeinsame Zuordnung von BehaviorSubject instance (t) abonniere, wird nur die erste Subskription ausgeführt.Die zweite Subskription für eine gemeinsame Zuordnung von BehaviorSubject wird nicht ausgeführt.

Wenn das Original BehaviorSubject (obj) einen zweiten Wert ausgibt, wird nur der letzte Wert gedruckt, und beide Abonnements wurden ausgeführt.

mein Code

const obj = new Rx.BehaviorSubject(1) 
obj.subscribe(console.log) 
const t = obj.map(u => { 
    console.log("mapped") 
    return u * 10 
}).share() 

t.subscribe(x => console.log("subscribe 1 " + x)) 
t.subscribe(x => console.log("subscribe 2 " + x)) 
//with the following line un-commented, both subscriptions print out new value 
//obj.next(2) 

Mein erwartetes Ergebnis ist

1 
mapped 
subscribe 1 10 
subscribe 2 10 

aber das tatsächliche Ergebnis war

1 
mapped 
subscribe 1 10 

Sorry für die naive Frage Let überprüfen. Kann mir das jemand erklären?

Vielen Dank

Antwort

0

In Ihrem Beispiel:

  • die BehaviorSubject in obj.

  • Subject Instanz innerhalb .share().

Denken Sie daran, dass BehaviorSubject seinen zwischengespeicherten Wert emittiert nur, wenn Sie es abonnieren.

Der erste Beobachter obj.subscribe(console.log) abonniert direkt die BehaviorSubject. Dies druckt 1.

Dann erstellen Sie eine Kette t, die mit dem Operator share() endet.

Jetzt abonnieren Sie t mit t.subscribe. Dies bedeutet, dass Sie die Subject innerhalb share() abonnieren, und da dies der erste Beobachter ist, muss er die Quelle Observable abonnieren (die wiederum die Quelle BehaviorSubject erreicht, die ihren zwischengespeicherten Wert ausgibt). Beachten Sie, dass share() nur eine Abkürzung für die Verwendung des Operators multicast() mit refCount() ist.

Und die letzte Zeile, die Sie erneut abonnieren mit t.subscribe. Genau wie zuvor abonniert dies die Subject innerhalb share(). Allerdings ist share() bereits auf seine Quelle Observable abonniert, so dass es nicht ein weiteres Abonnement macht. Das ist der Punkt des Multicasting und der Operator multicast().

Deshalb werden Sie keine subscribe 2 10 sehen, und Sie werden kein Ereignis siehe mapped zweimal gedruckt. Sie abonnieren die Subject innerhalb share(), nicht die Quelle BehaviorSubject.

+0

Wissen Sie, wie Sie ein 'BehaviorSubject' einem anderen' BehaviorSubject' zuordnen. Ich möchte die Logik in 'map' nicht bei jedem Abonnement wiederholen, sondern muss diese Logik nur dann ausführen, wenn die ursprüngliche' BehaviorSubject' -Instanz ('obj') einen neuen Wert ausgibt. Mit anderen Worten, ich möchte, dass etwas das Ergebnis als * erwartetes Ergebnis * in meiner Frage ausgibt. – transang

+0

Ich denke, dass ich meine Antwort aus @olsns Antwort bekommen habe. Vielen Dank – transang

1

Jeder Unternehmer (einschließlich der share) tatsächlich schafft einen neuen Sub-Observable, die seine eigene Anteil/Wiedergabe-Eigenschaften hat, die von der Quelle beobachtbare abgelöst werden.

Um Ihr Ergebnis zu erhalten, sollten Sie publishReplay(1) statt share() verwenden. (Mit publishReplay Sie haben natürlich entweder refCount() oder connect() zu verwenden) Sie haben zwei Themen

const obj = new Rx.BehaviorSubject(1) 
 
obj.subscribe(console.log) 
 
const t = obj.map(u => { 
 
    console.log("mapped") 
 
    return u * 10 
 
}).publishReplay(1) 
 
.refCount(); 
 

 
t.subscribe(x => console.log("subscribe 1 " + x)) 
 
t.subscribe(x => console.log("subscribe 2 " + x)) 
 
//with the following line un-commented, both subscriptions print out new value 
 
//obj.next(2)
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

Verwandte Themen