我使用产生大量事件的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
答案 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);