使用First()和Repeat()而不重新启动整个流RxJS

时间:2018-02-04 15:57:14

标签: node.js ecmascript-6 rxjs

我正在使用RxJS构建交易机器人。为此,我必须将套接字连接中的自动收报机数据转换为每隔x秒发出的蜡烛。

我创建了socketObservable这样的

const subscribeObservable = Observable.fromEventPattern(h => bittrex.websockets.subscribe(['USDT-BTC'], h))
const clientCallBackObservable = Observable.fromEventPattern(h => bittrex.websockets.client(h))

const socketObservable = clientCallBackObservable
  .flatMap(() => subscribeObservable)
  .filter(subscribtionData => subscribtionData && subscribtionData.M === 'updateExchangeState')
  .flatMap(exchangeState => Observable.from(exchangeState.A))
  .filter(marketData => marketData.Fills.length > 0)
  .map(marketData => marketData && marketData.Fills)

哪种方式正常 - 当我连接到客户端i flatMap到订阅连接时。

然后我有导致问题的candleObservable

export const candleObservable = (promise, timeFrame = TIME_FRAME) =>
  promise
    .scan((acc, curr) => [...acc, ...curr])
    .skipWhile(exchangeData => dateDifferenceInSeconds(exchangeData) < timeFrame)
    // take first after skipping
    .first()
    // first will complete the stream, so we repeat it
    .repeat()
    // we create candle data from the timeFrame array
    .map(fillsData => createCandle(fillsData))
    // accumulate candles
    .scan((acc, curr) => [...[acc], curr])

我想要实现的是积累数据,直到我有一个可以x秒的完整蜡烛。然后我想采取发射并重置扫描功能,所以我开始新的蜡烛。然后我创建蜡烛并在另一次扫描中累积它。

我的问题是,当我致电repeat()时,我的socketObservable也会再次被召唤。我不知道这是否会导致node-bittrex-api的任何开销,但我想避免它。

我已经尝试将累积的蜡烛部分放在一个平面地图或类似地图中但却无法使其工作。

你知道我怎么能避免repeat()整个流或其他方式制作蜡烛,我可以累积,然后在第一次发射后重置累加器?

1 个答案:

答案 0 :(得分:0)

从你所描述的内容来看,听起来你有一个观察,你想根据某些条件切入某种水桶。通常,将流减少到具有较少元素的另一流(没有过滤)被称为“背压”。在您的具体情况下,它听起来像您感兴趣的背压操作符是bufferbuffer运算符可以接受一个observable作为一个充当“关闭选择器”的参数,即可以使用此observable中的发射来调节何时绑定一个缓冲区并启动一个新缓冲区。

我建议您通过scan调用替换skipWhilefirstrepeatbuffer,并传入一个结果选择器“TIME_FRAME”到期时的值。这应该很容易表达为使用timer(在固定金额的情况下)或驱动流的去抖动版本(如果您想在数据中暂停时停止)的可观察性。如果你的缓冲区是严格基于时间的,那么甚至还有一个名为buffer的{​​{1}}专门化来处理这个问题。因为您最终会得到一个可观察的数组(而不是原始值),您可能希望用常规数组bufferTime替换最终的scan

如果没有更简单的例子,很难给出具体的代码。我建议您查阅各种背压操作员的示例代码,看看您是否能找到类似于您尝试实现的内容。