scala 如何将ApiFuture转换为ZIO任务?

wvt8vs2t  于 2023-10-18  发布在  Scala
关注(0)|答案(2)|浏览(141)

我正在使用Firebase,所以我有很多ApiFuture<A>类型的返回类型。我想把它们变成一个Task[A]与ZIO效果工作。

fdbelqdn

fdbelqdn1#

我们可以创建一个方法来使用Typeclasses转换它们:

trait EffectUtils[F[_]] {
  def toEffect[A](a: F[A]): Task[A]
}

object EffectUtils {

  implicit val apiFuture: EffectUtils[ApiFuture] = new EffectUtils[ApiFuture] {
    override def toEffect[A](a: ApiFuture[A]): Task[A] = Task.effectAsync[A]( cb =>
      ApiFutures.addCallback(a, new ApiFutureCallback[A] {
        override def onFailure(t: Throwable): Unit = cb(Task.fail(t))
        override def onSuccess(result: A): Unit = cb(Task.succeed(result))
      })
    )
  }

  implicit class ApiFutureOps[A](f: ApiFuture[A]) {
    def toEffect(implicit instance: EffectUtils[ApiFuture]) = instance.toEffect(f)
  }
}

现在,当我们发出一个API请求并想将结果转换为ZIO类型时,很容易:

import EffectUtils._

object App {
  // calling a Firebase function
  val record: Task[UserRecord] = firebase.getInstance().auth().getUserByEmailAsync(email).toEffect
icnyk63a

icnyk63a2#

对于ZIO v2.0+,函数Task.effectAsync不再可用。
但解决办法比尼姆罗德的答案更简单:

import com.google.api.core.*
import zio.*

extension [A] (apifuture: ApiFuture[A]){

  def toTask: Task[A] = ZIO.async( handler =>
    ApiFutures.addCallback(apifuture, new ApiFutureCallback[A] {
        override def onFailure(t: Throwable): Unit = handler(ZIO.fail(t))
        override def onSuccess(result: A): Unit = handler(ZIO.succeed(result))
      })
  )
}

相关问题