【问题标题】:What is the purpose of doOnNext(...) in RxJavaRxJava 中 doOnNext(...) 的目的是什么
【发布时间】:2020-09-29 05:19:46
【问题描述】:

我们什么时候应该使用 Observable 中的doOnNext() 而不是只使用 onNext()?

【问题讨论】:

  • 我注意到您正在使用 [system.reactive] 处理非 Rx.NET 问题...请记住,这是针对 .NET Rx 问题的。专门针对 RxJava 的问题不应该使用它。
  • 我注意到 rxsystem.reactive 的同义词 - 试图在 meta 上解决这个问题,以便它是一个单独的更通用的标签。

标签: java rx-java


【解决方案1】:

doOnNext 用于副作用:您希望在流的中间步骤中对项目排放做出反应(例如记录),例如在过滤流之前,用于日志记录等横向行为,但您仍然想要向下传播的值。

onNext 更最终,它消耗值。

【讨论】:

  • 我想知道为什么我不能将“日志”语句直接放在 Observable 中......即在订阅者/观察者上调用 onNext(...) 的类
  • 你绝对可以。只是该值可能已被后续转换丢失(例如,将所有值记录在 doOnNext 中,然后过滤一些值并仅在过滤后的值上应用 onNext)
  • 你怎么称呼onNext
  • @IgorGanapolsky onNextObserver(或Subscriber)接口的一部分,您通过subscribe(...) 方法在流的末尾插入该接口以使用最终值流
  • @SimonBaslé 它在哪个调度程序上运行?
【解决方案2】:

重要的编辑:-下面的粗体字符-

* 一旦掌握了这个概念, 我强烈建议您看看这个link,它改变了生活,不仅因为我们使用不同的可观察对象,如ObservableSingleMaybe,可能需要不同的工具,如doOnEvent() for @ 987654328@ 和 doOnEach() 用于 Observable 但是因为如果你想调试,有一些原因为什么 doOnNext() 通常甚至不是理想的选择,因为我们可以忽略与解决问题相关的其他事件*

原始回复:-部分修改-

首先,doOnNext() 可以在 Observable 和 Subscribe 之间的运算符链中调用更多次,这为您提供了更多调试代码的可能性。由于其“流”性质,在 RXJava 中不容易进行调试,doOnNext() 反而使调试更容易。为此,您还可以考虑将其与doOnError() 运算符结合使用。为什么不使用简单的onNext()?因为调试与代码的逻辑没有严格的关系,理论上你也可以在生产前去掉doOnNext()

要理解的一个非常重要的事情是,给定一个订阅长链的 Observable,您可以在特定点使用 doOnNext,以查看操作员正在回馈给另一个操作员:

例如:

Observable.just("Donald", "Duck", "Mickey", "Goofy",
                "Uncle")
                .doOnNext{System.out.println("Here ou will get the strings above:$it ")}
                 .map{it.length}
                 .subscribe { println("Here you will get the numbers of how every string is long: $it") }}

使用doOnNext() 的典型用例可能发生在您想要缓存来自服务器的响应时,例如您可以使用map()also doOnNext(),因为它允许您您的代码更具可读性,因为您可以放置​​一个简单的onNext(),理想情况下可以按照其他说明进行结构化。 (正如所有的架构思想一样,这是有争议的)

等同于doOnNext(),用于相同的调试目的 您可以使用其他不言自明的运算符:

doOnSubscribe()、doOnUnsubscribe()、doOnCompleted()、doOnError()、 doOnTerminate(),finallyDo(), doOnEach(), doOnRequest()

doOnNext() 让您可以看到 Observable(通常很长)链中发生了什么,真正重要的是 您可以在不影响任何操作的情况下窥探链中发生的事情,没有进行任何转换(假设不是我们在命令式代码中使用的Log.d,而不是响应式代码)。这就是为什么称为 side 效果。

编辑(因为 cmets 中的问题):

doOnNext()和上面的方法只是回调,请参考官方文档所说的thatdoOnNext()

只是修改一个 Observable 以便它在调用时调用一个动作 onNext。

真的很简单,这就是为什么有时会调用来上传进度条,但也确实用于存储库模式,例如,如果您想在调用改造后将数据存储到数据库/或缓存。

如果你真的很好奇,doSomethingReactive 方法只需在“真实”方法 SomethingReactive 中调用方法 call()(来自接口操作的回调)

【讨论】:

  • 对吗:onNext 只有在所有 doOnNext 完成任务后才会执行?就像我修改 doOnNext 中的值一样,onNext 会收到这个修改后的值吗?
  • 不,我认为不正确。我添加了一个编辑注释以使您更容易理解 doOnWhatever 反应式,请参阅上面的内容。 doOnNext 在调用每个 onNext 之前执行!正如您可以从 Log 示例中轻松看到的那样,您可以自己制作
  • 现在这是一个很好的答案。干得好
  • 我可以在订阅前多次调用doOnNext(consumer),它会在所有消费者上执行accept()吗?
  • @luis_cortes 非常感谢您的介入,我小时候发过这个帖子,现在我删除了进度条内容,并添加了一些关于 doOnNext 限制的新 imo 重要内容调试(希望不要超出 OP 问题范围),一旦程序员开始编写更复杂的链,请仔细检查是否喜欢
猜你喜欢
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多