在Node应用程序中,我尝试使用RxJS处理事件流。事件流是许多文档的更改列表。我使用groupBy通过documentId将流分区为新流。但我想知道,一旦文档在客户端关闭并且没有新的事件添加到该documentId的流中,groupBy会在该文档为空时处理该文件的流吗?如果没有,我将如何手动执行此操作?我想避免因创建新文档流而导致内存泄漏但从未被破坏。
答案 0 :(得分:2)
我建议做什么:
不是只有 documentChanges 可观察,而是 documentEvents 可观察。
客户端在打开文档时会发送 documentOpened 事件,在更改文档时发送 documentChanged 事件,在关闭文档时发送 documentClosed 事件
通过同一个observable发送所有3种类型的事件,您可以建立并保证订购。如果客户端按顺序发送 documentOpened , documentChanged , documentClosed 事件,那么您的服务器将按此顺序查看它们。请注意,对于由2个不同客户发送的事件顺序不会有任何保证。这样可以确保特定客户端发送的事件按顺序排列。
然后,这就是您使用groupByUntil
的方式:
documentEvents
.groupByUntil(
function (e) { return e.documentId; }, // key
null, // element
function (group) { // duration selector
var documentId = group.key;
return group.filter(function (e) { return e.eventType === 'documentClosed'; });
})
.flatMap(function (eventsForDocument) {
var documentId = eventsForDocument.key;
return eventsForDocument.whatever(...);
})
.subscribe(...);
另一个更简单的选项:您可以在闲置期后使该组到期。根据您对事件的处理情况,这可能绰绰有余。如果文档未在5分钟内编辑,则此示例将使组到期。如果进行了更多编辑,则会启动新组。
var idleTime = 5 * 60 * 1000;
events
.groupByUntil(
function(e) { return e.documentId; },
null,
function(g) { return g.debounce(idleTime); })
.flatMap...
答案 1 :(得分:1)
由于你包含了.NET标记,我也将介绍Rx.NET。
你的问题有点不正确。当且仅当他们从未有过事件时,流才是空的。所以,他们不能变成为空。不发送数据的流通常不会在资源方面消耗太多。
在.NET中,在源终止之前,组不会终止。我们使用'GroupByUntil`,它允许您为每个组指定durationSelector流。 Observable.Timer通常适用于此。
这意味着您可能会获得多个非并发流,并且随着时间的推移出现相同的密钥,但如果(通常情况下)您的组流在某个时刻被展平,则无关紧要。
在rxjs中,我们也有groupByUntil。
在Rx-Java中,表现相似的groupByUntil方法已归入groupBy - 有关详细信息,请参阅https://github.com/ReactiveX/RxJava/pull/1727和https://github.com/benjchristensen/RxJava/commit/b9302956832e3e77579f63fd9db25aa60eb4192a。
http://reactivex.io/documentation/operators/groupby.html说:
如果您取消订阅其中一个GroupedObservable,则GroupedObservable将被终止。如果源Observable稍后发出一个项,其键与以这种方式终止的GroupedObservable匹配,则groupBy将创建并发出一个新的GroupedObservable以匹配该键。
因此,在Rx-Java中,您必须取消订阅分组的可观察流才能终止它。带有takeUntil
信息流的timer
可以为此工作。
附录:
在回复您的评论时,在下游运营商取消订阅之前,流不会终止。 groupByUntil的持续时间选择器将导致终止。如果文档在关闭后不会再次打开,那么您只需将“documentclosed”事件发送到流中,并使用常规groupBy对“documentClosed”进行takeWhile测试。
重要的是文档未重新打开的原因是因为使用groupBy(在rx-js和rx.net中),如果已经看到的键重新出现,则不会创建新组。
如果这是一个问题,那么您将需要使用groupByUntil并使用已发布的流来监视documentClosed事件 - 使用已发布的流将确保您不会收到订阅副作用。