当前位置: 首页 > 知识库问答 >
问题:

如何在没有阻塞的情况下,在空单声道之后链接反应式操作?

石正信
2023-03-14

基本上,我试图实现的是调用第二个存储库(一个ReactiveCrudRepository)或抛出一个异常,这取决于调用第一个存储库的结果。

我最初的想法是这样的:

java prettyprint-override">/** Reactive with blocking code */
public Flux<SecondThing> getThings(String firstThingName) {
    FirstThing firstThing = firstRepo
        .findByName(firstThingName)
        // Warning: "Inappropriate blocking method call"
        .blockOptional()  // this fails in test-context
        .orElseThrow(() -> new FirstThingNotFound(firstThingName));

    return secondRepo.findAllByFirstThingId(firstThing.getId());
}

这将对应于以下非反应性方法:

/** Non-reactive */
public List<SecondThing> getThings(String firstThingName) {
    FirstThing firstThing = firstRepo
        .findByName(firstThingName)
        .orElseThrow(() -> new FirstThingNotFound(firstThingName));

    return secondRepo.findAllByFirstThingId(firstThing.getId());
}

我还没有找到一种方法来以反应性非阻塞的方式做到这一点。所有我需要的是抛出一个错误,如果一个空的Mono出来的第一个调用,并继续管道,如果不是空的;但我似乎不能使用onErrorStopdoOnError在这里正确,和map没有帮助,因为它跳过了空的Mono

如果我使用id而不是name,我有一个解决办法,但我不太满意它,因为它在第一件事的实例没有链接到它的情况下显示了不同的行为:

/** Reactive workaround 1 */
public Flux<SecondThing> getThings(Long firstThingId) {
    return secondRepo
        .findAllByFirstThingId(firstThingId)
        .switchIfEmpty(
            Flux.error(() -> new FirstThingNotFound(firstThingName))
        );
}

我发现的另一个解决方案是以下内容,它将空的Mono替换为null值,但它看起来不正确,并且也会引发警告:

/** Reactive workaround 2 */
public Flux<SecondThing> getThings(String firstThingName) {
    return firstRepo
        .findByName(firstThingName)
        // Warning: "Passing 'null' argument to parameter annotated as @NotNull"
        .defaultIfEmpty(null)
        .flatMapMany(
            firstThing -> secondRepo.findAllByFirstThingId(firstThing.getId()
        )
        .onErrorMap(
            NullPointerException.class, e -> new FirstThingNotFound(firstThingName)
        );
}

什么是正确的方法来链对两个存储库的调用,以便与请求的firstThingName一起存在或不存在FirstThing条件调用到第二回购?

共有1个答案

云宏儒
2023-03-14

我找到了一个如此简单的解决方案,以至于我为没有更早地找到它而感到羞愧:

public Flux<SecondThing> getThings(String firstThingName) {
    return firstRepo
        .findByName(firstThingName)
        .switchIfEmpty(Mono.error(() -> new FirstThingNotFound(firstThingName)))
        .flatMapMany(
            firstThing -> secondRepo.findAllByFirstThingId(firstThing.getId()
        );
}

诀窍在于switchiffempty不会强制您选择“有效”的替换值,因此可以使用Mono。错误直接传播正确的异常。

 类似资料:
  • 我正在调用一个外部服务来获取,如果该服务不工作,我所需要的只是用填充值

  • 假设我有这个方法: 我想调用这个方法,获取字符串,将该字符串转换为整数7,然后以非阻塞方式返回该整数。我该怎么做? 我试过这个,但是函数阻塞(同步): 我尝试使用代替(异步): 但是我得到了这个错误:<代码>类型不匹配:无法从int转换为Mono 那我该怎么办?

  • 问题内容: 构建通知时,如何发出没有声音的通知?我正在构建通知,我的用户不喜欢它发出声音的事实。 如何将其更改为无声/无声? 我如何显示通知: 我尝试在Google上进行搜索,但我得到的唯一结果是如何播放声音,而不是不播放声音… 编辑 在某些人看来,它可能是重复的,但是在我的我无法找到指定默认值的替代方法,而此新方法称为setDefaults 问题答案: 删除的行。它不会播放声音,但是如果需要,您

  • 我有一个存储库,它返回一个流量,并希望将结果设置为另一个需要列表的对象。有没有其他方法可以在不阻塞的情况下以列表的形式获取结果? 这座大楼正在运转,但需要很长时间。

  • 我的目标很简单,但不幸的是,我在反应式编程方面完全是新手: 具有<代码>单声道

  • 问题内容: 我想向服务器发送命令,并确定是否得到响应。 现在,我正在使用的函数,该函数会阻塞直到服务器发出响应,但我要做的就是首先确认服务器是否响应。 我尝试使用或避免此阻止,但这无济于事。 这导致我的程序陷入等待服务器响应的困境,这种情况永远不会发生。根据我对事物的理解,似乎做同样的事情。 我在此处找到的关于该主题的其他问题没有回答我的问题,所以请您回答我的问题会很好。 问题答案: 可能您所需要