我发送请求 - 获取数据数组。为了操纵那些数据,我需要将它弄平,所以我可以将它用作实体流而不是实体数组的流,但是在副作用上我希望这些实体一次出现在UI中,而不是一个接一个地出现在UI中,因此它一次仅更新UI。
我们说我有这样的代码:
// this generates a sequence of objects - getCasesStream sends an ajax request,
// whenever dateRange changes
casesStm = dateRangeStm.flatMapLatest(getCasesStream)
casesStm.subscribe((x)=> { console.log(x) })
function getCasesStream(dateRange) {
return getCases(dateRange.startDate, dateRange.endDate)
// api every time returns an array,
// but it's difficult to work with array of elements, ergo the flattening
.flatMap((x) => x)
.filter((x) => _.isNotEmpty(x.value))
.map((caseDoc) => _.assign(caseDoc.value, {
key: caseDoc.id
}));
}
这很好用,一次发出一个值。现在我想要的是发出最多10个值,如果少于10个 - 发出任何剩余的值。
我认为我可以通过这样做来解决这个问题:
casesStm
.windowWithCount(10)
.flatMap((x)=> x.toArray())
但是这只有在getCasesStream
(过滤后)至少返回10个项目时才有效,如果它少于那个 - 我甚至不会看到它们。
如何在这里有效缓冲元素?再次:
也许我应该使用返回window
中元素长度的泛型getCasesStream
,但该函数不会接受任何参数,我怎样才能获得长度?我尝试使用windowWithTimeOrCount
- 每隔一段时间就会发出空缓冲区,即使没有元素。
答案 0 :(得分:1)
您可以过滤掉这些空缓冲区,也可以查看How to create a RxJS buffer that groups elements in NodeJS but that does not rely on forever running interval?中提到的一些选项。
这个想法展示了将操作符buffer
与关闭选择器一起使用。作为结束选择器,您可以使用前面提到的链接中提出的merge(source.skip(9).take(1).repeat(), source.delay(Xms))
(或运算符flatMapFirst
,查看这两个选项)。以这种方式,原则上在没有发出的情况下,没有缓冲区发出,当一个案例到达时,merge
运算符在第10个案例或者之后的Xms(以先到者为准)发出一个值。当发出merge
运算符的值时,缓冲区将被关闭并发出。
您可以从这里的代码中获取灵感:
function emits(who){
return function (x) { console.log([who, "emits"].join(" ") + " " + x + " click(s)");};
}
var Xms = 1700;
var source = Rx.Observable.fromEvent(document.body, 'click');
console.log("running");
var delayedSource$ = Rx.Observable.merge(source.skip(9).take(1).repeat(), source.delay(Xms));
var buffered$ = source
.buffer(function () { return delayedSource$;}).map(function(clickBuffer){return clickBuffer.length;});
buffered$.subscribe(emits("buffer"));
jsbin:http://jsbin.com/siqopuxoli/edit?html,js,console,output
重要提示:您还应该共享您的案例来源(除非您知道它已经是热门资源),因为它将多次订阅:getCases(dateRange.startDate, dateRange.endDate).share()