有人可以帮助我理解以下之间的区别:
Mono.defer()
Mono.create()
Mono.just()
如何正确使用?
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
。
虽然总的来说我同意(并赞扬)@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)))
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) 方法