您可以使用Arrow FX将此代码转换为monad理解吗?

问题描述

您可以将此反应性方法转换为Arrow Fx Project Reactor monad comprehension吗?

class applicationserviceImpl(private val applicationRepository: ApplicationRepository,private val clientRepository: ClientRepository) : applicationservice {

    override fun findByProjectId(clientId: String,projectId: String): Flux<ApplicationOut> {
        return clientRepository.findById(clientId)
                .switchIfEmpty(ClientDoesntExistException(clientId).toMono())
                .flatMapMany { client ->
                    applicationRepository.findByProjectIdOrderByNameAsc(projectId).map {
                        it.convertToApplicationOut(client.timeZone)
                    }
                }
    }

}

我已经尝试过类似的操作,但是无效。

我发现的第一个问题是,最初我使用flatMapMany将Mono转换为Flux。如果我使用FluxK.monad().fx.monad clientRepository.findById(clientId).k().bind()没有可用的.bind()函数

如果我改用MonoK.monad().fx.monad,则不知道如何将输出转换为Flux:

    override fun findByProjectId(clientId: String,projectId: String): Flux<out ApplicationOut> {

        return FluxK.monad().fx.monad {
            val client = clientRepository.findById(clientId).k().bind()
            if (client != null) {
                !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .map { it.convertToApplicationOut(client.timeZone) }.k()
            } else {
                throw !ClientDoesntExistException(clientId).toMono<ApplicationOut>().k()
            }
        }.fix().flux

更新

按照El Paco的回答,我已将代码修改为:

        return FluxK.monad().fx.monad {
            val client = !clientRepository.findById(clientId).toFlux().k()
            if (client != null) {
                !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .map { it.convertToApplicationOut(client.timeZone) }.k()
            } else {
                !ClientDoesntExistException(clientId).toFlux<ApplicationOut>().k()
            }
        }.fix().flux

clientRepository.findById(clientId)存在时,它可以正常工作。如果不这样做,它会退出解析(不执行其他操作),而不是为val client分配null,因此我无法从解析内部启动异常,我猜这是正常的。

考虑以下方法,在该方法中,我需要控制两种情况,即客户端或项目不存在:

    return clientRepository.findById(clientId)
            .switchIfEmpty(ClientDoesntExistException(clientId).toMono())
            .flatMapMany { client ->
                applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .switchIfEmpty(ClientDoesntExistException(projectId).toMono())
                        .map { it.convertToApplicationOut(client.timeZone) }
            }

考虑到if / else方法不起作用时,如何使用理解力处理那些不存在的情况?

我可以在理解范围之外使用switchIfEmpty运算符,但我不知道原因(客户端不存在而项目不存在)

    return FluxK.monad().fx.monad {
        val client = !clientRepository.findById(clientId).toFlux().k()
        !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
              .map { it.convertToApplicationOut(client.timeZone) }.k()        
    }.fix().flux
            .switchIfEmpty(XXX)

解决方法

您应该将所有操作都转换为Flux,clientRepository.findById(clientId).toFlux().k()

此外,您无需抛出该异常即可打破束缚。

!ClientDoesntExistException(clientId).toMono<ApplicationOut>().k()