请问Rx.Observable.group可以清理空流吗?

时间:2015-05-21 16:17:27

标签: javascript system.reactive reactive-programming rx-java reactive-extensions-js

在Node应用程序中,我尝试使用RxJS处理事件流。事件流是许多文档的更改列表。我使用groupBy通过documentId将流分区为新流。但我想知道,一旦文档在客户端关闭并且没有新的事件添加到该documentId的流中,groupBy会在该文档为空时处理该文件的流吗?如果没有,我将如何手动执行此操作?我想避免因创建新文档流而导致内存泄漏但从未被破坏。

2 个答案:

答案 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/1727https://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事件 - 使用已发布的流将确保您不会收到订阅副作用。

相关问题