使用redux-observable

时间:2017-10-30 17:15:39

标签: rxjs buffer redux-observable

我使用产生大量事件的WebSocket服务,我想缓冲一些由WS事件触发的动作,具体取决于存储中指定的时间(缓冲可以被禁用,因此也可以是0毫秒)。至于现在,我有类似的东西:

const eventEpic = (action$, store) => {
    return action$.ofType(ACTION)
        ::bufferWhen((action) => {
            const { time } = action.payload;

            return time > 0
                ? Observable.interval(time)
                : action$.ofType(ACTION);
        })
        ::map((bufferedActions) => writeToStoreAction(...));
};

此解决方案有效,但我觉得可以更好地实施。

bufferWhen提供了函数,该函数返回指示何时应关闭缓冲区的流 - 如果指定时间则返回interval,如果没有,则在收到ACTION后立即关闭流。

这种做法是否正确? ; - )

此致 Mateusz

2 个答案:

答案 0 :(得分:1)

实现这个目标

  

缓冲一些动作......取决于商店中指定的时间......希望避免多次访问商店

const time$ = Observable.of(this.store.getBufferTime());

const eventEpic = (action$, store) => {
  return time$.switchMap(time => {
     action$.ofType(ACTION)
       ::bufferWhen(() => Observable.interval(time) )
       ::map((bufferedActions) => writeToStoreAction(...));
   }
};

我不熟悉史诗,所以你可能不得不调整它。

修改

实际上,由于bufferWhen不再具有条件逻辑,

     action$.ofType(ACTION)
       ::buffer(Observable.interval(time))

编辑#2

上述代码中出现了一些问题

1)空缓冲区发出
buffer返回一个值数组,但有时数组可以为空,因为触发缓冲区刷新的Observable.interval(time)可以比 更快 缓冲的事件率。当时间=== 0'时这很明显,但是当&time;时间>时也会出现这种情况。 0&#39 ;.
简单的解决方法是过滤掉空缓冲区。

2)失去的事件
switchMap更改时,time会导致丢失事件,并且新的内部observable会替换旧的内部可观察对象。旧内部可观察缓冲区中的任何事件都不会被发出,因此会丢失 解决此问题的方法是向缓冲区触发器添加flush事件。 do运算符在switchMap运行
之前将flush事件发送到内部可观察 。尝试使用time$代替flush$并不起作用。

const time$ = Observable.of(this.store.getBufferTime());
const flush$ = new Rx.Subject()

const eventEpic = (action$, store) => {
  return time$
    .do(x => flush$.next(true))
    .switchMap(time => 
      action$.ofType(ACTION)
        ::buffer(Observable.interval(time).merge(flush$))
        ::filter(events => events.length > 0)
        ::map((bufferedActions) => writeToStoreAction(...));
};

答案 1 :(得分:0)

很抱歉,回复需要很长时间,但实际上我的缓冲解决方案会随着时间的推移进行评估,并且必须处理更多案例。

请在下面找到我的最终解决方案。希望它会帮助某人;)

    AbstractCsvParser parser = new AbstractCsvParser();

    List<AliasLocus> aliases = parser.readCsvFile(
            "aliases.csv",
            AliasLocusMapper.FILE_HEADER_MAPPING,
            AliasLocusMapper::mapRecord);

    List<Product> products = parser.readCsvFile(
            "products.csv",
            ProductMapper.FILE_HEADER_MAPPING,
            ProductMapper::mapRecord);