【问题标题】:Mono.Defer() vs Mono.create() vs Mono.just()?Mono.Defer() vs Mono.create() vs Mono.just()?
【发布时间】:2019-09-30 14:19:48
【问题描述】:

有人可以帮我理解以下之间的区别:

  • Mono.defer()
  • Mono.create()
  • Mono.just()

如何正确使用?

【问题讨论】:

    标签: spring-webflux project-reactor


    【解决方案1】:

    Mono.just(value) 是最原始的——一旦你有了一个值,你就可以把它包装成一个 Mono 并且订阅者会得到它。

    Mono.defer(monoSupplier) 允许您提供整个表达式来提供结果 Mono 实例。这个表达式的评估被推迟到有人订阅。在此表达式中,您还可以使用Mono.error(throwable) 之类的控制结构来指示错误条件(您不能使用Mono.just 执行此操作)。

    Mono.create(monoSinkConsumer) 是最先进的方法,可让您完全控制发出的值。无需从回调中返回Mono 实例(如Mono.defer),您可以控制MonoSink<T>,让您可以通过MonoSink.success()MonoSink.success(value)MonoSink.error(throwable) 方法发出值。 Reactor 文档包含一些可能的 Mono.create 用例的好示例:link to doc

    一般建议是使用最不强大的抽象来完成这项工作:Mono.just -> Mono.defer -> Mono.create

    【讨论】:

    • 如果有订阅者,我可以说 Mono.defer 和 Mono.create 会被执行吗?那么 Mono.just 呢?我仍然不知道什么时候使用它。当我尝试 mono.map(result -> methodA()).switchIfEmpty(Mono.just()) 时,此代码将在 map 之前先运行 mono.just。其实我还是觉得switchIfEmpty会在map之后执行,因为它需要检查map是否返回空然后去switchIfEmpty。但是当我尝试 mono.map(result -> methodA()).switchIfEmpty(Mono.create(...)) 它将获得所需的结果流
    • 你是对的。在 Mono.defer 和 Mono.create 中通过使用 Supplier 和 Consumer 来实现惰性(延迟评估)的效果。您不会将实际结果传递给他们,而是传递一个表达式,该表达式稍后会给出预期结果。 Mono.just 通常在您已经有一个计算值或者您希望在构建反应式管道时立即计算该值时使用。
    • 在您的第一个示例中,预计您在 Mono.just 中输入的任何内容都将在 map 内部的表达式之前计算(如果没有人订阅,甚至永远无法计算)。 Mono.create 和 Mono.deferred 将按照您的描述运行。
    【解决方案2】:

    虽然总的来说我同意(并赞扬)@IlyaZinkovich 的回答,但我会谨慎对待建议

    一般建议是使用最不强大的抽象来完成这项工作:Mono.just -> Mono.defer -> Mono.create

    在反应式方法中,特别是如果我们是初学者,很容易忽略“最不强大的抽象”实际上是哪个。除了@IlyaZinkovich,我没有说别的,只是描述了一个细节方面。

    我想添加一个特定用例,其中Mono.defer()Mono.just() 更可取,但乍一看可能看不到这一事实。

    我们使用switchIfEmpty() 作为订阅时间分支:

    // First ask provider1
    provider1.provide(someData)
        // If provider1 did not provide the result, ask the fallback provider provider2
        .switchIfEmpty(provider2.provide(someData))
    

    provider2.provide() 仅当provider1.provide() 不返回任何结果时才接受someData和/或provider2.provide() 返回的Mono 的方法组合可能很昂贵,甚至失败当调用错误的数据时。

    这种情况defer() 更可取,即使它可能乍一看还不清楚:

    provider1.provide(someData)
        // ONLY IF provider1 did not provide the result, assemble another Mono with provider2.provide()
        .switchIfEmpty(Mono.defer(() -> provider2.provide(someData)))
    

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 2011-09-18
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      • 2010-12-09
      • 2017-06-20
      相关资源
      最近更新 更多