简体   繁体   中英

Rx.js, using Subject to multicast from Observable

If there are any Rx.js experts out there? I'm trying to multicast an observable by using a subject, as per the instructions on any number of websites, including rx.js docs.

var mainDataSource = Rx.Observable.from(summaries[0].added)
  //add a timestamp to each live entry as it passes through
  .timestamp()
  .map(function(scriptElement) { 
     var array = [scriptElement, scriptElement.timestamp]; return array; 
  })
  //check contents of the array
  .do(function(array) { console.log(array); });

var multicaster = new Rx.Subject();
var subSource = mainDataSource.subscribe(multicaster);
//attach the inline observer to the multicaster subject
multicaster.subscribe(
    function (x) { console.log('Value published to inlineScriptObserver: ' + x); },
    function (e) { console.log('onError: ' + e.message); },
    function () { console.log('inlineScriptObserver onCompleted'); }
);
//attach the external observer to the multicaster subject
multicaster.subscribe(
    function (x) { console.log('Value published to externalScriptObserver: ' + x); },
    function (e) { console.log('onError: ' + e.message); },
    function () { console.log('externalScriptObserver onCompleted'); }
);

And the output I'm getting is as follows:

[Object, 1493425651491]
inlineScriptObserver onCompleted
externalScriptObserver onCompleted

So the Subject and the Observable are clearly connected as the onCompleted event is being transmitted from one to the other. However I am getting no data travelling alongside. The data in the correct format is there at the end of the Observable but it is not printing in the console from the Subject's Observer.

What am I missing? It's eluding me.

OK, it may be bad form answering your own question but in case anyone else comes along with the same problem...

The docs I read must have been outdated, relating to rx.js 4 not 5, or something. As of today, and according to this page,

https://github.com/ReactiveX/rxjs/blob/master/doc/subject.md

The correct syntax for the above example is as follows:

var multicaster = new Rx.Subject();
var mainDataSource = Rx.Observable.from(summaries[0].added)

//add a timestamp to each live entry as it passes through
.timestamp()
//log the timestamp for testing purposes
.do(function(scriptElement) { console.log("mainDataSource Timestamp: " + scriptElement.timestamp); })
//include the timestamp in array and deliver that array to subscribers
.map(function(scriptElement) { var array = [scriptElement, scriptElement.timestamp]; return array; })
//check contents of the array
do(function(array) { console.log(array); });

var multicastedDataSource = mainDataSource.multicast(multicaster);
//attach the inline observer to the multicaster subject
multicastedDataSource.subscribe(val => console.log(val), null, () => console.log('inlineScriptObserver complete'));
//attach the external observer to the multicaster subject
multicastedDataSource.subscribe(val => console.log(val), null, () => console.log('externalScriptObserver complete'));
multicastedDataSource.connect();

The key differences being the use of multicast() rather than subscribe on the observable and then the requirement to connect() to the subject piping the multicasted observable as well as having the observers subscribing.

No wonder my older rx.js book was so cheap on Amazon...

Either subscribe before firing an events or use ReplaySubject. See the working fiddle :

var mainDataSource = Rx.Observable.from([1, 2, 3])
  //add a timestamp to each live entry as it passes through
  .timestamp()
  .map(function(scriptElement) { 
     var array = [scriptElement, scriptElement.timestamp]; return array; 
  })
  //check contents of the array
  .do(function(array) { console.log(array); });

var multicaster = new Rx.ReplaySubject();
var subSource = mainDataSource.subscribe(multicaster);
//attach the inline observer to the multicaster subject
multicaster.subscribe(
    function (x) { console.log('Value published to inlineScriptObserver: ' + x); },
    function (e) { console.log('onError: ' + e.message); },
    function () { console.log('inlineScriptObserver onCompleted'); }
);
//attach the external observer to the multicaster subject
multicaster.subscribe(
    function (x) { console.log('Value published to externalScriptObserver: ' + x); },
    function (e) { console.log('onError: ' + e.message); },
    function () { console.log('externalScriptObserver onCompleted'); }
);

The output is:

[Object, 1493467831996]
[Object, 1493467831999]
[Object, 1493467832000]
Value published to inlineScriptObserver: [object Object],1493467831996
Value published to inlineScriptObserver: [object Object],1493467831999
Value published to inlineScriptObserver: [object Object],1493467832000
inlineScriptObserver onCompleted
Value published to externalScriptObserver: [object Object],1493467831996
Value published to externalScriptObserver: [object Object],1493467831999
Value published to externalScriptObserver: [object Object],1493467832000
externalScriptObserver onCompleted

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM