如何将ApiFuture类型转换为ZIO的Task类型?
Firebase ApiFuture 转 ZIO Task 实现方案
ApiFuture<A>是Google官方提供的异步返回类型,本质为Guava ListenableFuture的子类,可通过以下两种方案转换为ZIO的Task[A]类型适配函数式开发:
方案1:原生异步封装(无需额外依赖)
通过ApiFuture自带的回调接口直接封装为ZIO异步Task,适合不想引入额外依赖的场景:
import com.google.api.core.{ApiFuture, ApiFutureCallback, ApiFutures} import zio.Task import java.util.concurrent.Executor def apiFutureToTask[A](future: => ApiFuture[A])(implicit exec: Executor): Task[A] = Task.async { callback => ApiFutures.addCallback( future, new ApiFutureCallback[A] { override def onFailure(t: Throwable): Unit = callback(Left(t)) override def onSuccess(result: A): Unit = callback(Right(result)) }, exec ) }
参数说明:
- 入参
future: => ApiFuture[A]采用惰性求值声明,避免ApiFuture在ZIO调度执行前提前触发,符合纯函数effect的懒执行特性 - 隐式参数
exec可传入项目自定义线程池,也可直接使用ZIO内置线程池:zio.Runtime.defaultExecutor.asJava
方案2:基于ZIO Guava互操作库实现
如果项目允许引入第三方互操作依赖,可使用zio-interop-guava简化实现,依赖坐标(SBT):"dev.zio" %% "zio-interop-guava" % "31.0.1.0"
转换代码:
import com.google.api.core.ApiFuture import zio.Task import zio.interop.guava._ def apiFutureToTask[A](future: => ApiFuture[A]): Task[A] = Task.fromListenableFuture(future)
优化使用体验
可以通过隐式扩展方法简化全局调用,无需每次手动包裹转换函数:
implicit class ApiFutureOps[A](private val future: => ApiFuture[A]) extends AnyVal { // 对应方案1的扩展方法,若使用方案2可去掉implicit exec参数 def toTask(implicit exec: Executor): Task[A] = apiFutureToTask(future) } // 调用示例:直接对Firebase返回的ApiFuture调用toTask即可 val getUserTask: Task[UserRecord] = FirebaseAuth.getInstance().getUserAsync("target-uid").toTask
注意事项
- 转换后的
Task[A]天然支持ZIO所有内置操作符,可直接使用retry、timeout、race等能力 - 不要提前求值ApiFuture实例,保证转换过程的纯函数特性,避免副作用提前触发
内容的提问来源于stack exchange,提问作者Nimrod Sadeh
相关产品推荐
相关产品推荐

