有几种方法可以被视为异常抛出的一种方便方法:
处理元素时使用
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
向下游发出信号。反过来,我们可以使用相同的
手柄
操作员。一旦把手
BiConsumer
在执行过程中,没有提供任何元素,反应堆会将其视为一种过滤,并会为我们请求一个额外的元素。最后,如果元素有效,我们可以简单地调用
SynchronousSink#next
并向下游传播元素或在其上应用一些映射,因此我们将
手柄
作为
map
这里是接线员。此外,我们可以在不影响性能的情况下安全地使用该运算符,并提供复杂的元素验证,如元素验证或发送到下游的错误。
投掷使用
#concatMap
+
Mono.error
在映射期间引发异常的选项之一是替换
地图
具有
concatMap
. 本质上,
连接图
差不多一样吗
flatMap
做。唯一的区别是
浓度图
一次只允许一个子流。这种行为大大简化了内部实现,并且不会影响性能。因此,我们可以使用以下代码以更实用的方式抛出异常:
Mono.just(userId)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Mono.error(new InvalidUserException());
}
return Mono.just(user);
})
在上面的示例中,如果用户无效,我们将使用返回异常
单项误差
. 我们可以用同样的方法处理通量
Flux.error
:
Flux.just(userId1, userId2, userId3)
.map(repo::findById)
.concatMap(user-> {
if(!isValid(user)){
return Flux.error(new InvalidUserException());
}
return Mono.just(user);
})
注释
,在这两种情况下,我们都会返回
寒冷的
只有一个元素的流。在反应器中,有两个优化可以在回流是冷的情况下提高性能。
标量
流。因此,建议使用Flux/Mono
连接图
+
.just
,
empty
,
error
因此,当我们需要更复杂的映射时,最终可能会
return null
或
throw new ...
.
注意!永远不要检查可空性上的传入元素。反应堆项目将永远不会发送
null
因为这个暴力反应流规范(参见
Rule 2.13
)
因此,如果
repo.findById
返回空值,反应器将为您抛出NPE异常。
等等,为什么
连接图
比…好
平版地图
是吗?
本质上,
平版地图
用于合并一次执行的多个子流中的元素。这意味着flatmap下面应该有异步流,因此它们可能在多个线程上处理数据,或者可能是多个网络调用。随后,这种期望对实现有很大影响,因此
平版地图
应该能够处理来自多个流的数据(
Thread
s)(表示并发数据结构的使用),如果从另一个流中排出,则将元素排队(表示为
Queue
对于每个子流),不要违反反应流规范规则(意味着真正复杂的实现)。把所有这些事实和我们取代一个
地图
以更方便的方式使用
Flux/Mono.error
(这不会改变执行的同步性)导致了这样一个事实,即我们不需要如此复杂的运算符,我们可以使用更简单的
连接图
它是为一次异步处理一个流而设计的,为了处理标量的冷流,它有两个优化。
使用引发异常
switchOnEmpty
因此,当结果为空时引发异常的另一种方法是
转换空
操作员。下面的代码演示了如何使用这种方法:
Mono.just(userId)
.flatMap(repo::findById)
.switchIfEmpty(Mono.error(new UserNotFoundExeception()))
我们可以看到,在这种情况下
repo::findById
应该有
Mono
属于
User
作为返回类型。因此,在案例A中
用户
找不到实例,结果流将为空。因此,反应堆将调用另一种方法
单声道
,指定为
switchIfEmpty
参数。
按原样抛出异常
它可以被视为一个不太可读的代码或糟糕的实践,但您可以按原样抛出异常。此模式违反了反应流规范,但反应器将为您捕获抛出的异常并将其作为
出错
向下游发出信号
外卖
-
使用
把手
提供复杂元素处理的运算符
-
使用
连接图
+
单项误差
当我们需要在映射期间抛出异常时,这种技术最适合于异步元素处理的情况。
-
使用
平版地图
+
单项误差
当我们已经
平版地图
到位
-
Null
因为返回类型是禁止的,所以
无效的
在你的下游
地图
你会得到意想不到的
出错
具有
NullPointerException
-
使用
开关空
在所有情况下,如果调用某个特定函数的结果完成了
空的
流动