将 `com.ning.http.client.ListenableFuture[Any]` 转换为 `scala.concurrent.Future[Any]`

convert `com.ning.http.client.ListenableFuture[Any]` into `scala.concurrent.Future[Any]`

有什么方法可以将类型 com.ning.http.client.ListenableFuture[A] 的变量转换为类型 scala.concurrent.Future[A]

换句话说,函数的内容是什么

def toFuture[A](a: com.ning.http.client.ListenableFuture[A]):scala.concurrent.Future[A] = ???

我具体是A = com.ning.http.client.Response

的情况

请注意 com.ning.http.client.ListenableFuture[A]com.google.common.util.concurrent.ListenableFuture 不同(因此 this proposed duplicate 不能解决问题)

这个想法与 guava 的 ListenableFuture 相同,尽管由于更受限制的签名而受到更多限制。

首先,您需要获得一个 java.util.concurrent.Executor 来添加回调。由于您的 Scala 代码与 Java 库交互,我建议根据 Java Executors 定义 scala.concurrent.ExecutorServices 池 - 这样您就可以保留 Executor 的实例和一个 ExecutorService,类似于以下内容:

import java.util.concurrent.Executors
import scala.concurrent.ExecutionContext
val executor = Executors.newFixedThreadPool(5) // use it for Java futures
implicit val executionContext = ExecutionContext.fromExecutor(executor) // use it for Scala futures

如果你想处理不同池中的所有内容,则不需要上述步骤。如果您想使用现有的 ExecutionContext,这里有一个 snippet 我用谷歌搜索过。

然后,要将 ListenableFuture 转换为 Future,我会这样做(考虑到 java.util.concurrent.Future 的一些异常语义):

def toFuture[A](a: ListenableFuture[A]): Future[A] = {
  val promise = Promise[A]()
  a.addListener(new Runnable {
    def run() = {
      try {
        promise.success(a.get)
      } catch {
        case ex: ExecutionException => promise.failure(ex.getCause)
        case ex => promise.failure(ex)
      }
    }
  }, executor)
  promise.future
}