RxJs - 每秒聚合事件和重置扫描

时间:2017-12-24 04:35:05

标签: rxjs

我试图创建一个可以在范围内聚合事件的观察点 - 但是我无法重置聚合。

const events = new Rx.Subject();

// example
// create a reactive stream of BTC completed transactions
// aggregate the highs/lows over one second
const btc = events
    .filter(f => f.product_id === "BTC-USD" && f.type === "done")
    .window(Rx.Observable.interval(1000))
    .mergeAll()
    .scan((acc, i) => {
        //console.log(i);
        let price = i.price;
        if (i.price) {
            if (acc.high === -1 || price > acc.high) acc.high = price;
            if (acc.low === -1 || price < acc.low) acc.low = price;
            acc.last = price;
        }
        return acc;
    }, { high: -1, low: -1, last: -1, ts: (new Date()).getTime().toString() })
    .window(Rx.Observable.interval(1000))
    .map(j=> j.last())
    .mergeAll();

// output the stream of aggregates every second
btc.subscribe(j=>console.log(j));

由于我在聚合累加器中有一个时间戳,我可以告诉我们我们在窗口之间保持聚合。

{ high: '14725.97000000',
  low: '14106.01000000',
  last: '14150.52000000',
  ts: '1514089269250' }
{ high: '17279.27000000',
  low: '14059.87000000',
  last: '14162.09000000',
  ts: '1514089269250' }

如何重置扫描?或通过其他方式实现同​​样的目标?

2 个答案:

答案 0 :(得分:0)

将第一个mergeAllscan替换为mergeMap - 在其中执行scan

const btc = events
    .filter(f => f.product_id === "BTC-USD" && f.type === "done")
    .window(Rx.Observable.interval(1000))
    .mergeMap(w => w.scan((acc, i) => {
        let price = i.price;
        if (i.price) {
            if (acc.high === -1 || price > acc.high) acc.high = price;
            if (acc.low === -1 || price < acc.low) acc.low = price;
            acc.last = price;
        }
        return acc;
      }, { high: -1, low: -1, last: -1, ts: (new Date()).getTime().toString() })
    )
    .window(Rx.Observable.interval(1000))
    .map(j=> j.last())
    .mergeAll();

此外,如果您使用reduce代替scan,则不需要第二个window等,因为reduce将仅发出最后一个值:< / p>

const btc = events
    .filter(f => f.product_id === "BTC-USD" && f.type === "done")
    .window(Rx.Observable.interval(1000))
    .mergeMap(w => w.reduce((acc, i) => {
        let price = i.price;
        if (i.price) {
            if (acc.high === -1 || price > acc.high) acc.high = price;
            if (acc.low === -1 || price < acc.low) acc.low = price;
            acc.last = price;
        }
        return acc;
      }, { high: -1, low: -1, last: -1, ts: (new Date()).getTime().toString() })
    );

答案 1 :(得分:0)

实际上我认为我们不需要在这里扫描如果我正确理解你的任务。试试这个例子:

var openings = Rx.Observable.interval(3000);

// Convert the window to an array
var source = Rx.Observable.timer(0, 100)
    .window(openings)
    .take(3) // restrict values just for example
    .flatMap(function (x) { 
    let arrayedValues = x.toArray();
    //Here you can caluculate high, low, last, ts
    return arrayedValues; 
    });

source.subscribe(
(x) => console.log(x)

plunker