使用Arrow-kt和Kotlin处理异步结果

我有两个对外部系统的异步函数调用,返回任何一个<Exception,Something>,并且需要合并它们的结果。作为 Arrow-Kt 函数式编程的初学者,我想知道完成这项任务的最佳方式是什么。以下是我目前正在使用的代码。它当然有效,但并不真正“感觉”是最直接的。我正在寻找一种更“实用”的风格来获得结果。注意:需要预先使用成功的 List 结果。

suspend fun getAs(): Either<Exception, List<A>> = TODO()
suspend fun getBs(): Either<Exception, List<B>> = TODO()
suspend fun doSomethingWithA(listA: List<A>): Unit = TODO()

launch {
    val deferredA = async { getAs() }
    val deferredB = async { getBs() }

    either<Exception, List<A>> {
        val listOfAs = deferredA.await()
            .bimap(leftOperation = { e ->
                println("special message on error for A")
                e
            }, rightOperation = { listA ->
                doSomethingWithA(listA)
                listA
            })
            .bind()
        val listOfBs = deferredB.await().bind()

        listOfAs.filter { it.someId !in listOfBs.map { it.someProperty } }
    }
    .map { /* handle result */ }
    .handleError { /* handle error */ }

}

另一种选择是map{}像这样使用函数

launch {
    val deferredA = async { getAs() }
    val deferredB = async { getBs() }

    deferredA.await()
        .bimap(leftOperation = { e ->
            println("special message on error for A")
            e
        }, rightOperation = { listA ->
            doSomethingWithA(listA)
            deferredB.await().map { listB ->
                listA.filter { a -> a.someId !in listB.map { it.someProperty } }
            }
        })
        .map { /* handle result */ }
        .handleError { /* handle error */ }
}

回答

最简单的方法是结合either { }使用parZip
either { }允许你提取AEither<E, A>,并且parZip是用于运行效用函数suspend并行功能。

suspend fun getAs(): Either<Exception, List<A>> = TODO()
suspend fun getBs(): Either<Exception, List<B>> = TODO()
suspend fun doSomethingWithA(listA: List<A>): Unit = TODO()

either {
  val list = parZip(
    {
       getAs()
         .mapLeft { e -> println("special message on error for A"); e }
         .bind()
    },
    { getBs().bind() },
    { aas, bbs ->
      aas.filter { a -> a.someId !in bbs.map { it.someProperty }
    }
  )

  /* Work with list and return value to `either { } */
}.handleError { /* handle error */ }

这里bind()摘录AEither<E, A>. 我们在内部parZip这样做,这样每当Left遇到a时,它就会使either { }块短路,通过这样做,它还取消了仍在运行的任务parZip

这样,如果getAs()立即返回Left,然后它成为产值either { }getBs()被取消。


以上是使用Arrow-kt和Kotlin处理异步结果的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>