问题
I 've removed the boilerplate to get to the point
// a.js
// My observables from stream and event
this.a = Rx.Node.fromStream(this.aStream());
this.itemSource = Rx.Observable.fromEvent(ee, 'addItem');
// Zip 'em
this.itemcombo = Rx.Observable.zip(this.a, this.itemSource, function (s1, s2) {
return {item: s2, a: s1.toString()};
});
// Streams the lowercase alphabet
rb.prototype.aStream = function aStream() {
var rs = Readable();
var c = 97;
rs._read = function () {
rs.push(String.fromCharCode(c++));
console.log('Hit!');
if (c > 'z'.charCodeAt(0)) {
rs.push(null);
}
};
return rs;
};
// b.js
(requires the module exported above)
rb.enqueue('a'); // The method simply does an ee.emit('addItem', ...) in the module to trigger the itemSource observable
What I expected to see:
{item: 'a', a: 'a'}
printed in the console
What happened:
Hit!
was printed 24 times before {item: 'a', a: 'a'}
. This means that zip
took all the values from aStream
, buffered them and then did what it was supposed to do.
How do I get the same functionality zip
offers but lazily? My goal is to use an infinite stream/observable and zip it with a finite (async) one.
Edit
See/Edit it via runnable: RX Zip test Edit 2 Code updated based on answer -> no output now.
回答1:
zip
is indeed lazy. It just subscribes to a
and b
and does its work whenever either produces a new value.
Your problem is that fromStream
is emitting all of its values synchronously as soon as zip
subscribes to it. This is happening because your custom Readable
is constantly saying "There is more data available!"
Make your Readable
asynchronous and you'll get the desired behavior.
Try something like this (untested)
var rs = Readable();
var subscription = null;
rs._read = function () {
if (!subscription) {
// produce the values once per second
subscription = Rx.Observable
.generateWithRelativeTime(
97, // start value
function (c) { return c > 'z'.charCodeAt(0); }, // end condition
function (c) { return c + 1; }, // step function
function (c) { return String.fromCharCode(c); }, // result selector
function () { return 1000; }) // 1000ms between values
.subscribe(
function (s) {
rs.push(s);
console.log("Hit!");
},
function (error) { rs.push(null); },
function () { rs.push(null); });
}
};
来源:https://stackoverflow.com/questions/25524671/rxjs-zip-is-not-lazy