在使用RxJS5实现我想要的东西时遇到一些麻烦 - 我有一个简单的Observables链,以Rx.Observable.interval开头:
const Rx = require('rxjs');
var i = 0;
const obs = Rx.Observable.interval(100)
.flatMap(function () {
return Rx.Observable.timer(Math.ceil(500*Math.random()))
.map(function(val){
console.log(' => These should all log first => ', val);
return i++;
});
})
.take(5)
.merge() // this doesn't seem to do what I want to do
.map(function (val) {
console.log('all done = > ', val);
});
obs.subscribe();
上面记录了这个:
=> These should all log first => 0
all done = > 0
=> These should all log first => 0
all done = > 1
=> These should all log first => 0
all done = > 2
=> These should all log first => 0
all done = > 3
=> These should all log first => 0
all done = > 4
我希望记录下来:
=> These should all log first => 0
=> These should all log first => 0
=> These should all log first => 0
=> These should all log first => 0
=> These should all log first => 0
all done = > [0,1,2,3,4]
很明显,我们并没有等待所有的计时器观察结果完成,因为你会看到"所有完成!"记录了很多次,穿插了"这些应该首先记录"。
如何获得我想要的输出?
通常情况下,我们可以使用zip
,但zip
的API不适合此用例,因为我们不会在同一个地方同时拥有所有计时器可观察量时间!
如果我的问题不够清楚,这就是我想要做的类比,我们阻止所有回调,直到我们任意完成并收集了所有结果:
const async = require('async');
var i = 0;
async.forever(function(cb){
process.nextTick(function(){
console.log('These should all log first');
const err = i++ === 5;
cb(err, i);
});
}, function done(err, results){
// let's pretend results contains all the i values
console.log('all done');
});
答案 0 :(得分:0)
请注意,这基本上会产生我期望看到的日志记录顺序,但我认为这不是正确/最好的方法:
const {Observable} = require('rxjs');
const obs = Observable.interval(100)
.flatMap(function () {
return Observable.timer(Math.ceil(500*Math.random()))
.map(function(val){
console.log(' => These should all log first => ', val);
});
})
.take(5)
.takeLast() // <<<<<<<<<<
.map(function () {
console.log('all done');
})
.take(1) // <<<<<<<<<<
obs.subscribe();
我认为还有更好的方法来实现这一目标。
答案 1 :(得分:0)
@jonsharpe给了我这个答案,基本上有效。问题实际上可以简化为Rx.Observable.interval
,我们可以摆脱Rx.Observable.timer
映射。这是我们的基本答案:
const Rx = require('rxjs');
const obs = Rx.Observable.interval(100)
.take(5)
.map(function(v){
console.log(v);
return v;
})
.reduce(function (prev, curr) {
return prev.concat(curr);
},[])
.last(function (results) {
return results;
})
.map(function(v){
console.log(v);
});
obs.subscribe();
然而,我会非常感兴趣,没有 reduce。
答案 2 :(得分:0)
所以要求是:
就是这样。这有点天真,但确实有效。
let timerArrLength = [ 4, 2, 3 ];
let svc = Rx.Observable.interval(1000)
.take(timerArrLength.length)
.map(function ( index ) {
let arr = [];
for ( let i = 0; i < timerArrLength [ index ]; i++ ) {
arr.push ( Rx.Observable.timer ( 1000 ) );
}
return arr;
});
svc.subscribe(
function onNext(v){
console.log('=> v =>',v);
},
function onError(e){
console.error(e);
},
function onComplete(){
console.log('complete');
}
);