سؤال

I am wondering how I can create an effect of windowWithMaxCount, which would work like windowWithCount but the window size would change from 1 to maxCount.

What I am doing is drawing a line chart base on c stream of events. The line chart needs array of let say 50 points. When new point is arrive I need to push one point out on the right and put this new point on the left.

So in general observable.windowWithCount(50,1) does exactly that. The only problem that for the first window I have to wait until all 50 elements become available. During this time users see nothing on the screen.

What I want to happen instead is as soon as a first point arrives I'd like to get window of size 1, then window of size 2 etc until I get to window of size 50 (maxCount). At this point all subsequent windows would be size 50.

The effect on the screen would be line filling the screen from left to right until it feels all screen.

هل كانت مفيدة؟

المحلول

What you're describing is bufferWithCount. In reality, windowWithCount yields an observable immediately, and that observable will begin yielding it's items immediately. Presumable, you are doing a toArray (or something similar) somewhere down the line, which is forcing the window to complete before yielding it's items. This is most likely because you are trying to synchronize all of your points before attempting to draw the image. Instead, you should be using the events as they come. However, if you were to do this, you would end up with duplicate draws, as the windows definitely overlap.

In reality, what you probably want is something more like 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);

This approach is also more effecient, as you're only creating one observable, rather than a new observable per each item.

If you wanted to generalize the approach, you could create an operator:

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]);
    });
};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top