RxJS可变长度窗口

时间:2014-05-05 18:32:12

标签: reactive-extensions-js rxjs

我想知道如何创建windowWithMaxCount的效果,它会像windowWithCount一样工作,但窗口大小会从1变为maxCount。

我正在做的是根据c流事件绘制折线图。折线图需要50个点数组。当新点到达时,我需要在右侧推出一个点并将这个新点放在左侧。

所以一般来说observable.windowWithCount(50,1)就是这么做的。第一个窗口的唯一问题是我必须等到所有50个元素都可用。在此期间,用户不会在屏幕上看到任何内容。

我想要发生的事情是,只要第一个点到达我就想获得大小为1的窗口,然后是大小为2的窗口,直到我到达大小为50的窗口(maxCount)。此时所有后续窗口的大小都为50。

屏幕上的效果将是从左到右填充屏幕,直到感觉到所有屏幕。

1 个答案:

答案 0 :(得分:0)

您所描述的是bufferWithCount。实际上,windowWithCount会立即产生一个可观察的,并且可观察的将立即开始产生它的项目。可以预测,你正在某个地方做一个toArray(或类似的东西),这会迫使窗口在产生它的物品之前完成。这很可能是因为您在尝试绘制图像之前尝试同步所有点。相反,您应该在事件发生时使用它们。但是,如果你这样做,你最终会得到重复的绘制,因为窗户肯定会重叠。

实际上,你可能想要的更像scan ......

var Rx = require('rx'),
    Observable = Rx.Observable,
    log = console.log.bind(console),
    source = Observable.interval(25),
    points = source.scan([], function (acc, point) {
        if (acc.length === 50) {
            // Remove the last item
            acc.shift();
        }

        // Add the next item
        acc.push(point);
        return acc;
    }),
    subscription = points.subscribe(log);

这种方法也更有效,因为你只为每个项目创建一个可观察的,而不是新的可观察数据。

如果您想概括该方法,可以创建一个运算符:

Rx.Observable.prototype.rollingBuffer = function (count) {
    return this.scan([], function (acc, point) {
        var length  = acc.length,
            start   = (length >= count)
                    ? (length - count + 1)
                    : 0;
        return acc
            .slice(start)
            .concat([point]);
    });
};