Mono.Defer() vs Mono.create() vs Mono.just()?

问题描述 投票:0回答:3

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

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

如何正确使用?

spring-webflux project-reactor
3个回答
54
投票

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
用例的好示例:链接到文档

一般建议是使用最不强大的抽象来完成这项工作:

Mono.just -> Mono.defer -> Mono.create


4
投票

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

一般建议是使用最不强大的抽象来完成这项工作:

Mono.just
->
Mono.defer
->
Mono.create

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

这是一个特定的用例,其中更强大抽象

Mono.defer()
Mono.just()
更可取,但乍一看可能不可见。

另请参阅:

我们使用

switchIfEmpty()
作为 订阅时间分支:

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

public Mono<MyResponse> provide2(MyRequest someData) {
    // The Mono assembly is needed only in some corner cases
    // but in fact it is always happening
    return Mono.just(someData)
        // expensive data processing which might even fail in the assemble time
        .map(...)
        .map(...)
        ...
}
仅当

provider2.provide2()

 不返回任何结果时,
someData
才接受
provider1.provide1()
Mono
 返回的 
provider2.provide2()
 的方法组装成本高昂,甚至在调用错误数据时会失败。

在这种情况下

defer()

是更好的选择,即使它
可能乍一看并不明显:

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

0
投票
public Mono<DrawDetail> getDrawDetail(int id, int year) { return drawDetailCacheService.getDrawDetail(year, id) .doOnNext(detail -> LOGGER.debug("draw detail {}-{} found in cache", year, id)) .switchIfEmpty( Mono.defer(() -> { LOGGER.debug("draw detail {}-{} not found in cache calling remote...", year, id); return Mono.just(callRemoteEventDetailAndSendToCache(id, year)); }) );
}

这是 Mono.just() 和 Mono.defer() 之间的区别:

当您使用 Mono.just(...) 时,just 中的参数会立即被求值。这意味着如果您写了:

.switchIfEmpty(Mono.just(callRemoteEventDetailAndSendToCache(id, year)))
无论缓存服务是否返回值,callRemoteEventDetailAndSendToCache(id,year)方法都会立即执行。这绝对不是您想要的,特别是如果该方法有副作用,例如进行远程调用或修改状态。

相反,当您使用 Mono.defer(...) 时,提供的 lambda 仅在 Mono 被订阅时执行。在 switchIfEmpty() 的上下文中,这意味着 lambda 仅当前面的 Mono(来自缓存服务)为空时才会执行。

通过使用 Mono.defer(),仅在需要时(即,当缓存没有 DrawDetail 时)才延迟调用 callRemoteEventDetailAndSendToCache(id,year) 方法

© www.soinside.com 2019 - 2024. All rights reserved.