javascript - 更智能的缓冲器

标签 javascript reactive-programming rxjs

我发送请求 - 获取数据数组。为了操作该数据,我需要将其展平,这样我可以将其用作实体流而不是实体数组流,但是,副作用是我希望这些实体立即出现在 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/

相关文章:

javascript - 包含小写、大写、字母数字、特殊字符的正则表达式,且一行中相同字符不超过 2 个,最小长度为 8 个字符

javascript - 在 Three.js 中重新定位纹理

haskell - 对 Yampa 开关的图表感到困惑

spring - 在 Spring WebFlux react 处理程序中发送 JMS 消息 : is it blocking?

angular - 订阅 FormBuilder valueChanges 时,使用 debounceTime 和 distinctUntilChanged 不起作用

javascript - 使用 jquery/javascript 单击切换

javascript - 使用箭头键移动 SVG 元素

java - RxJava : OnErrorFailedException. 确定正确原因

javascript - Cycle.js 应用程序未捕获的类型错误

javascript - 基于过滤器 RxJS 的不同管道