我发送请求 - 获取数据数组。为了操作该数据,我需要将其展平,这样我可以将其用作实体流而不是实体数组流,但是,副作用是我希望这些实体立即出现在 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 个项目时,这才有效,如果少于这个值 - 我什至不会看到它们。
如何在这里有效地缓冲元素?再次:
- api 向我们发送一个数组
- 要过滤并向每个元素添加额外的属性,最好展平该数组(或者也许不展平?)
- 最后我需要缓冲(不想强制浏览器在每次新元素出现时重绘)
也许我应该使用通用的window
来返回getCasesStream
中元素的长度,但该函数不接受任何参数,我如何获得长度?我尝试使用 windowWithTimeOrCount
- 每个时间间隔都会发出空缓冲区,即使没有元素也是如此。
最佳答案
您可以过滤掉那些空缓冲区,或者您可以查看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()
关于javascript - 更智能的缓冲器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33558225/