Skip to main content
Version: 2.0.x

How to Interop with Future?

Scala Future

Basic interoperability with Scala's Future is now provided by ZIO, and does not require a separate module.

From Future

Scala's Future can be converted into a ZIO effect with ZIO.fromFuture:

def loggedFuture[A](future: ExecutionContext => Future[A]): UIO[Task[A]] = {
ZIO.fromFuture { implicit ec =>
future(ec).flatMap { result =>
Future(println("Future succeeded with " + result)).map(_ => result)
}
}
}

Scala's Future can also be converted into a Fiber with Fiber.fromFuture:

def futureToFiber[A](future: => Future[A]): Fiber[Throwable, A] = 
Fiber.fromFuture(future)

This is a pure operation, given any sensible notion of fiber equality.

To Future

A ZIO Task effect can be converted into a Future with ZIO#toFuture:

def taskToFuture[A](task: Task[A]): UIO[Future[A]] = 
task.toFuture

Because converting a Task into an (eager) Future is effectful, the return value of ZIO#toFuture is an effect. To actually begin the computation, and access the started Future, it is necessary to execute the effect with a runtime.

A ZIO Fiber can be converted into a Future with Fiber#toFuture:

def fiberToFuture[A](fiber: Fiber[Throwable, A]): UIO[Future[A]] = 
fiber.toFuture

Run to Future

You can call .unsafe.runToFuture on an instance of Runtime to execute a ZIO effect asynchronously and return a Future that will be completed when the execution of the effect is complete.

import zio.{Runtime, Task, Unsafe}
...
val zio: Task[String] = ...
val runtime = Runtime.default
val fut: Future[String] = Unsafe.unsafe { implicit unsafe =>
runtime.unsafe.runToFuture(zio)
}