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

将两个单声道组合在一起,第二个单声道订阅第一个单声道

哈泰
2023-03-14

我最近一直在学习使用Java中的reactor库和Spring框架进行反应式编程,并且在很大程度上我已经能够掌握它。然而,我发现自己有好几次遇到同样的情况,我想知道我哪里出了问题。

我正在努力解决的问题的要点是,我经常想用mono做一些事情,比如找到一些补充数据,然后将其添加回原始mono中。zip函数在我看来是一个理想的候选函数,但最终我订阅了两次原始mono,这不是我的意图。

这里有一个人为的例子,我一直在试图解决这种情况,因为我无法分享我的公司代码。它假设我们使用的是一个反应式数据库,并设置了一个记录器,Person类是不可变的,但具有

public Mono<Person> getPersonWithFamilyMembers(Integer id){
    log.info("Finding person with id {}", id);

    personRepository.findById(id)
        .switchIfEmpty(Mono.error(NotFoundException::new))
        .doOnNext(person -> log.info("Found person: {}", person))
        .as(this::fetchAndAddFamilyMembers)
        .doOnSuccess(person -> log.info("Successfully found person with family members"));
}

private Mono<Person> fetchAndAddFamilyMembers(Mono<Person> personMono){
    Mono<List<Person>> familyMembersMono = personMono
        .map(Person::getFamilyId)
        .flatMapMany(PersonRepository::findByFamilyId)
        .collectList();

    return personMono.zipWith(familyMembersMono, Person::withFamilyMembers);
}

我在运行这样的代码时看到的输出是:

INFO | Finding person with id 1
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Found person: Person(id=1, familyId=1, familyMembers=[])
INFO | Successfully found person with family members

这确实是有意义的,因为原始人mono已经在两个地方订阅,在那里我将其映射到familyMembersMono中,并且当我将它们压缩在一起时,但是如果可以避免的话,我不想对存储库进行不必要的调用。

有人对处理这种行为的更好方法有什么建议吗?

共有1个答案

仲元凯
2023-03-14

一般来说,你不会“添加数据”到单声道,而是其中的数据。考虑到这一点,使用4A Map而不是作为

public Mono<Person> getPersonWithFamilyMembers(Integer id){
    log.info("Finding person with id {}", id);

    return personRepository.findById(id)
        .switchIfEmpty(Mono.error(NotFoundException::new))
        .doOnNext(person -> log.info("Found person: {}", person))
        .flatMap(this::fetchAndAddFamilyMembers)
        .doOnSuccess(person -> log.info("Successfully found person with family members"));
}

private Mono<Person> fetchAndAddFamilyMembers(Person person){ // this accepts Person, not Mono<Person>
    return personRepository.findByFamilyId(person.getFamilyId())
        .collectList()
        .map(person::withFamilyMembers);
}
 类似资料:
  • 我面临的情况是,我必须使用2 Mono,其中第二个将依赖于第一个的Id字段,并在第一个Mono的主体中返回第二个的响应。 例如: 然后将结果返回为 我试过了 但像这样,我只能返回第二个单声道的响应。 通过尝试Map或Flatmap,它只在第二个单声道上起作用。 请提出建议。

  • 我正在尝试创建以下链: 因此,我需要得到5。但是在执行1,2和3之前,4。 代码运行正常,但我想退出 从

  • 我想根据一些条件将结果从两个单声道组合起来。这两个单声道都是网络客户端调用的结果: 第一个是期望快速响应的单个呼叫。 第二个是几个响应缓慢的电话的组合。 如果第一个单声道的结果满足某些条件,则“取消”第二个单声道的想法可以节省时间并避免不必要的网络调用。如果第一个单声道的结果不够,请使用第二个单声道。 一个静态编程语言代码示例来解释我的想法: 更新: 更清楚的是,让我们假设平凡的结果在1秒内出现,

  • webflux包中发生了有趣的事情。然而,我在源头的旅程并没有解决以下问题。 假设我有以下单声道(或通量): 我在webfilter中使用类似的构造,用租户和用户数据丰富管道。然后在控制器中使用如下构造: hello mono的上下文填充在world mono中。我试图弄清楚这是如何做到的,也是为了单元测试的目的。 最后,这仍然是一个谜。我试图用单声道/通量对象上可用的常规方法来做到这一点,但是我

  • 获取所有分支 遍历所有并将其添加到 返回,这是我不确定这样做是否正确的地方。但它起作用了 合并所有列表 我只是困惑,这是在我的上下文中使用的正确方式吗?或者有没有什么更好的方法来实现我正在努力做的事情?

  • 我想创建一个SpringWebFlux服务,它将两个源的数据与一个依赖项相结合。我是Webflux的新手,所以我不知道怎么做。下面是一些伪代码来说明我要做的事情: 的结果包括我想用查找的数据的标识符。至少我想处理这两个数据集。我可以使用什么方法代替第一个?