我是反应式编程的新手,并且难以使用“一切都可以成为流”的口头禅。我正在考虑以下场景 - 我有一个 websocket事件流,如下所示:
Rx.Observable.create((observer) => {
io.on('connect', function(socket){
socket.on("enroll", function(player) {
observer.next({
event: 'enroll',
player,
socket
});
});
socket.on('resign', function(player){
observer.next({
event: 'resign',
player,
socket
});
});
});
return {
dispose: io.close
};
});
然后我可以做类似
的事情enrollmentStream = events$
.filter(find({ event: "enroll" }))
.map(pick('player'));
同样
resignationStream = events$
.filter(find({ event: "resign" }))
.map(pick('player'));
我想在一个流中收集已注册的玩家,这些玩家将在4个批处理中进行批量处理,但显然这应仅针对在注册流中但不在resignationStream中的用户或至少最后一个事件是注册的用户。我该怎么做?
这是大理石图。
有5名球员报名参赛。当有4名球员注册时,比赛开始。请注意,第二个玩家(紫罗兰色)注册但随后辞职,所以游戏不是以蓝色大理石开始,而是下一个 - 黄色 - 因为只有在那之后才有4名玩家准备就绪。
可能应该有一些像“没有”的流操作 ...是吗?
答案 0 :(得分:2)
我认为在这种情况下,您可以使用combineLatest()
和scan()
运算符,然后自行列出未签名的玩家:
const bufferedEnrollment = enrollmentStream.scan((acc, val) => { acc.push(val); return acc; }, []);
const bufferedResignation = enrollmentStream.scan((acc, val) => { acc.push(val); return acc; }, []);
Observable.combineLatest(bufferedEnrollment, bufferedResignation)
.map(values => {
const enrolled = values[0];
const resigned = values[1];
// remove resigned players from `enrolled` array
return enrolled;
})
.filter(players => players.length === 4)
.subscribe(...)
scan()
运算符仅用于将玩家收集到阵列中。例如,如果您希望能够重置数组,则可以将其与另一个Observable合并。
enrollmentStream
.merge(resetStream)
.scan((acc, val) => {
if (!val) {
return [];
}
acc.push(val);
return acc;
}, []);
(由于显而易见的原因,我没有测试此代码)。