我想缓冲流,直到流为谓词为真:
例如,数字可以除以5:
//emit value every 1 second
const oneSecondInterval = Rx.Observable.interval(1000);
//return an observable that checks if the number is divided by zero
const fiveSecondInterval = () => oneSecondInterval.filter(number => number % 5 === 0);
const bufferWhenExample = oneSecondInterval.bufferWhen(fiveSecondInterval);
//log values
const subscribe = bufferWhenExample.subscribe(val => console.log('Emitted Buffer: ', val));
输出
"Emitted Buffer: "
[]
"Emitted Buffer: "
[0, 1]
"Emitted Buffer: "
[2]
"Emitted Buffer: "
[3]
"Emitted Buffer: "
[4]
"Emitted Buffer: "
[5]
"Emitted Buffer: "
[6]
"Emitted Buffer: "
[7]
"Emitted Buffer: "
[8]
"Emitted Buffer: "
[9]
"Emitted Buffer: "
[10]
我想要的是什么:
"Emitted Buffer: "
[0]
"Emitted Buffer: "
[1,2,3,4,5]
"Emitted Buffer: "
[6,7,8,9,10]
但这不起作用。为什么呢?
DEMO:http://jsbin.com/durerimiju/1/edit?js,console
这几乎是好的
const oneSecondInterval = Rx.Observable.interval(1000);
const fiveSecondInterval = oneSecondInterval.filter(time => time % 5 === 0);
const bufferWhenExample = oneSecondInterval.buffer(fiveSecondInterval);
bufferWhenExample.subscribe(console.log)
唯一的问题是它会发出
[]
[0,1,2,3,4]
[5,6,7,8,9]
相反,我希望
[0]
[1,2,3,4,5]
[6,7,8,9,10]
答案 0 :(得分:2)
bufferWhen 运算符获取一个关闭的可观察工厂函数,该函数在每个缓冲区启动时创建observable。在您的情况下,对于每个缓冲迭代,它创建一个始终以0开始的新区间observable。
您可以简单地使用 buffer 运算符获取一个可观察的结果,它将按预期工作:
const oneSecondInterval = Rx.Observable.interval(1000);
const fiveSecondInterval = oneSecondInterval.filter((number) => number % 5 === 0);
oneSecondInterval.buffer(fiveSecondInterval);
我编辑了你的jsbin here
答案 1 :(得分:1)
interval
observable不会发出它已经消失的次数,它只会发出undefined
。因此,当您执行.filter(number => number % 5 === 0)
时,谓词始终返回false。
要计算已发出的值的数量,您可以使用.scan operator:
const fiveSecondInterval = () =>
oneSecondInterval
.scan(count => count + 1, 0)
.filter(count => count % 5 === 0);
答案 2 :(得分:0)
以下是适用于我的解决方案(在Typescript中):
import { interval, OperatorFunction } from 'rxjs';
import { buffer, delay, filter, share, tap } from 'rxjs/operators';
export function bufferUntil<T>(predicate:(value:T) => boolean):OperatorFunction<T, T[]>
{
return function(source)
{
const share$ = source.pipe(share());
const until$ = share$.pipe(filter(predicate), delay(0));
return share$.pipe(buffer(until$));
};
}
interval(1000).pipe(
tap(console.log),
bufferUntil(value => value % 5 === 0),
tap(console.log)
).subscribe();
这将产生以下输出:
0
[0] // this emits immediately after the previous log
1
2
3
4
5
[1, 2, 3, 4, 5] // this emits immediately after the previous log
6
7
8
9
10
[6, 7, 8, 9, 10] // this emits immediately after the previous log
如果有人有更好的解决方案,或者如果我的实现在某种程度上是危险的或不正确的,我很想听听它,因为我自己需要此功能。