更智能的缓冲区

时间:2015-11-06 01:59:52

标签: javascript reactive-programming rxjs

我发送请求 - 获取数据数组。为了操纵那些数据,我需要将它弄平,所以我可以将它用作实体流而不是实体数组的流,但是在副作用上我希望这些实体一次出现在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个项目时才有效,如果它少于那个 - 我甚至不会看到它们。

如何在这里有效缓冲元素?再次:

  • api向我们发送一个数组
  • 过滤并为每个元素添加额外的道具,以便更好地展平该阵列(或者可能不是?)
  • 最后我需要缓冲(不想在每次新元素出现时强制浏览器重绘)

也许我应该使用返回window中元素长度的泛型getCasesStream,但该函数不会接受任何参数,我怎样才能获得长度?我尝试使用windowWithTimeOrCount - 每隔一段时间就会发出空缓冲区,即使没有元素。

1 个答案:

答案 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()

相关问题