我是新来的项目Reactor和反应式编程一般。
我目前正在在一张类似下面的代码:
Mono.just(userId)
.map(repo::findById)
.map(user-> {
if(user == null){
throw new UserNotFoundException();
}
return user;
})
// ... other mappings
这个例子可能是愚蠢的,有一定落实这种情况下,更好的方式,但问题是:
这是错误的使用throw new
例外,在map
块或者我应该用return Mono.error(new UserNotFoundException())
代替呢?
有没有在做这两种方式中的任何实际的区别吗?
有一对夫妇的,可以被视为异常抛出的一种方便的方式方法:
Flux/Mono.handle
一的,可以简化其可能导致错误的或空的流的元素的处理的方式是操作者handle
。
下面的代码演示了如何使用它才能解决我们的问题:
Mono.just(userId)
.map(repo::findById)
.handle((user, sink) -> {
if(!isValid(user)){
sink.error(new InvalidUserException());
} else if (isSendable(user))
sink.next(user);
}
else {
//just ignore element
}
})
我们可以看到,在.handle
运营商需要通过BiConsumer<T, SynchronousSink<>
为了处理一个元素。在这里,我们有我们的BiConsumer两个参数。第一个是从上游,其中,第二个是SynchronousSink
这有助于我们同步供给元件到下游的元件。这种技术扩展到提供我们的元素的处理不同的结果的能力。例如,在情况下该元素是无效的,我们可以提供错误的相同SycnchronousSync
将上游取消并产生onError
信号到下游。反过来,我们可以“过滤器”使用相同的handle
运营商。一旦手柄BiConsumer
被执行,没有元素已经供应,反应堆将考虑作为类型的过滤,将请求对我们来说是额外的元素。最后,如果该元素是有效的,我们可以简单地调用SynchronousSink#next
和下游传播我们的元素或应用一些关于它的映射,所以我们必须handle
这里的map
操作。此外,我们可以放心地使用该运营商没有性能影响,并提供复杂的元素验证,如元素或错误发送给下游验证。
#concatMap
+ Mono.error
其中的映射过程中抛出一个异常的选项是map
更换concatMap
。在本质上,concatMap
做几乎同样的flatMap
一样。唯一的区别是,concatMap
允许一次只有一个子。这样的行为,简化内部实行了很多,不会影响性能。因此,我们可以使用下面的代码以抛出异常的一个功能更强大的方式:
Mono.just(userId)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Mono.error(new InvalidUserException());
}
return Mono.just(user);
})
另外,在上述中无效的用户的情况下,样品中,我们使用Mono.error
返回异常。同样,我们可以使用Flux.error
助焊剂做:
Flux.just(userId1, userId2, userId3)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Flux.error(new InvalidUserException());
}
return Mono.just(user);
})
请注意,在这两种情况下,我们返回的只有一个元素感冒流。在电抗器,有一对夫妇的改善情况下的性能优化的返回流是冷标量流。因此,建议使用流量/单声道concatMap
+ .just
,empty
,error
因此,当我们需要更复杂的映射,可与return null
或throw new ...
结束。
注意!永远不要检查为空传入的元素。该反应堆项目将永远不会给你发送一个
null
值,因为这违反了无流规范(见Rule 2.13)因此,在情况下,如果repo.findById
返回null,反应堆将抛出NullPointerException为您服务。
concatMap
is better than flatMap
?在本质上,flatMap
被设计为合并从在时间执行所述多个子元件。这意味着flatMap应该有异步流之下的话,他们可能会在处理多个线程的数据,或者可能是几个网络调用。随后,这种预期的冲击实现了很多,所以flatMap
应该能够处理来自多个流(Thread
s)数据(指并发数据结构的使用),排队元素如果存在来自另一个流的排水(用于Queue
s附加存储器分配每个子),不违反无流规范规则(指非常复杂的实现)。计算所有这些事实,我们更换一个普通map
操作(这是同步的)事实在使用Flux/Mono.error
(不更改执行的同步性)抛出异常的更方便的方法会导致这样的事实,我们不需要这样的复杂的操作,我们可以使用它在一个时间设计为单流的异步处理,并有几个优化,以处理标量,寒溪水简单得多concatMap
。
switchOnEmpty
因此,另一种方法抛出一个异常时,则结果为空是switchOnEmpty
操作。下面的代码演示了如何使用这种方法:
Mono.just(userId)
.flatMap(repo::findById)
.switchIfEmpty(Mono.error(new UserNotFoundExeception()))
正如我们所看到的,在这种情况下repo::findById
应该有Mono
User
作为返回类型。因此,万一User
实例不会被发现,结果流将是空的。因此,反应器将调用一个替代Mono
,指定为switchIfEmpty
参数。
它可算作一个不太可读的代码或不好的做法,但你可以把你的异常,因为是。这种模式违反了无流规范,但反应器将捕捉抛出的异常,为您和传播它作为onError
信号到你的下游
.handle
运营商,以提供复杂的元素处理concatMap
+ Mono.error
。flatMap
的返回类型是在你的下游Mono.error
禁止的所以不是flatMap
你会得到与Null
意外null
map
在所有情况下,当你需要的,如果调用一些特定功能的结果与空流完成后发送错误信号