首页 > 解决方案 > 如果找到值但不执行其他步骤,则返回 Mono.empty()

问题描述

这个问题很难用文字来描述,所以如果标题不符合要求,很抱歉。

我想用 Project Reactor Flux 和 Mono 来实现一个特定的目标,乍一看似乎很简单。

“阻塞方式”中的代码示例将比长描述更好:

    fun findGroupToCreateBlocking(userId: UUID, groupLabel: String): Optional<LinkUserToGroup> {
        val group = lib.findGroupsOfUser(userId)
                .flatMapIterable { it.items }
                .filter { it.label == groupLabel }
                .toMono()
                .blockOptional()

        if(group.isPresent) {
            return Optional.empty()
        }

        return lib.searchGroups(groupLabel)
                .flatMapIterable { it.items }
                .filter { it.label == groupLabel }
                .toMono()
                .map { LinkUserToGroup(userId, it.id) }
                .switchIfEmpty { IllegalStateException("Group $groupLabel not found").toMono() }
                .blockOptional()
    }

当然,我尝试在没有这block部分的情况下实现相同的目标。我最终得到以下代码:

fun findGroupToCreateReactive(userId: UUID, groupLabel: String): Mono<LinkUserToGroup> =
            lib.findGroupsOfUser(userId)
                    .flatMapIterable { it.items }
                    .filter { it.label == groupLabel }
                    .toMono()
                    .map { Optional.of(it) }
                    .defaultIfEmpty(Optional.empty())
                    .filter { g -> g.isEmpty }
                    .flatMap { lib.searchGroups(groupLabel)
                            .flatMapIterable { it.items }
                            .toMono()
                            .map { LinkUserToGroup(userId, it.id) }
                            .switchIfEmpty { IllegalStateException("Group $groupLabel not found").toMono() }
                    }

我认为(而且我不是唯一一个)我们可以做得更好,而不是依赖于Optional流中间的使用......但我没有找到任何其他解决方案。

这是我第四次与这种“模式”作斗争,所以欢迎一些帮助!

我已经在 Gitlab (这里) 上生成了一个演示项目,其中包含对机器人反应和阻塞实现的单元测试,以查看命题是否符合要求。如果需要,您可以分叉并使用该项目。

标签: reactive-programmingproject-reactorreactive

解决方案


我没有使用 a Mono.empty,而是使用了该Flux.hasElement方法(如@yossarian),但添加了一个否定过滤器。它似乎可以工作,因为单元测试仍然通过。

    fun findGroupToCreateReactive(userId: UUID, groupLabel: String): Mono<LinkUserToGroup> =
            lib.findGroupsOfUser(userId)
                    .flatMapIterable { it.items }
                    .map { it.label }
                    .hasElement(groupLabel)
                    .filter { g -> !g }
                    .flatMap { lib.searchGroups(groupLabel)
                            .flatMapIterable { it.items }
                            .toMono()
                            .map { LinkUserToGroup(userId, it.id) }
                            .switchIfEmpty { IllegalStateException("Group $groupLabel not found").toMono() }
                    }

由于我们只想在用户不属于某个组时才搜索组,因此使用否定过滤器会更加明确。


推荐阅读