如何在Scala中失败承诺



在Scala文档中,有一个示例如何选择未来通过承诺更快地成功的示例。

http://docs.scala-lang.org/overviews/core/futures.html#promises

def first[T](f: Future[T], g: Future[T]): Future[T] = {
  val p = promise[T]
  f onSuccess {
    case x => p.trySuccess(x)
  }
  g onSuccess {
    case x => p.trySuccess(x)
  }
  p.future
}

此功能返回未来成功的未来,如果其中任何一个都失败了,则永远不会完成。

是否可以以某种方式对此进行修改,即使其他未来失败了,第二个是成功的,并且两个都成功了,那么越来越较快的速度就会像现在一样挑选。

您可以添加此:

f onFailure {
  case e =>
    g onFailure {
      case _ =>
        p.failure(e)
    }
}

两个期货失败时,这将使承诺失败,而异常与f相同。您可以对此进行详细说明,以创建一个例外,该异常记录了来自fg的2个异常。

我建议您遵循Alvin Alexander在Scala中的期货和承诺的建议

我相信这是与期货合作的最佳方法

package futures
import scala.concurrent.{Future => ConcurrentTask}           // rename
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import Utils.sleep
object FutureAsConcurrentTask extends App {
  // run some long-running task (task has type Future[Int] in this example)
  val task = ConcurrentTask {
    Cloud.executeLongRunningTask
  }
  // whenever the task completes, execute this code
  task.onComplete {
    case Success(value) => println(s"Got the callback, value = $value")
    case Failure(e) => println(s"D'oh! The task failed: ${e.getMessage}")
  }
  // do your other work
  println("A ..."); sleep(100)
  println("B ..."); sleep(100)
  println("C ..."); sleep(100)
  println("D ..."); sleep(100)
  println("E ..."); sleep(100)
  println("F ..."); sleep(100)
}

这是选择最快的未来的基本模式,如果它们都太慢了:

import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{ Success, Failure }
import akka.actor._
import akka.pattern.after
object GetFastestFutureOrTimeout extends App {
  val e = new TimeoutException("TimeoutException")
  val system = ActorSystem("GetFastestFutureOrTimeout")
  val f1 = Future { Thread.sleep(200); "this is f1" }
  val f2 = Future { Thread.sleep(100); "this is f2" }
  val timeoutFuture = after(500.milliseconds, using = system.scheduler) { Future.failed(e) }
  val f = Future.firstCompletedOf(f1 :: f2 :: timeoutFuture :: Nil)
  f onComplete {
    case Success(msg) => println(msg)
    case Failure(err) => println("An error occured: " + err.getMessage)
  }
}

此打印"这是F2"。如果TimeOutFuture的超时更改为50,则将打印"发生错误:TimeOutException"。

在引擎盖下,FirstCompletedOf使用承诺返回完成的第一个未来的价值,请访问https://github.com/scala/scala/scala/blob/v2.11.6/src/library/scala/scala/scala/concurrent/concurrent/future/future/future.scala#l503。

这是一个基本的实现,以获取最快的成功响应,或者如果他们都失败了:

def getFirstSuccessfulResultOrFail[T](requests: List[Future[T]]): Future[T] = {
  val p              = Promise[T]()
  val countDownLatch = AtomicInt(0)
  requests.foreach { f =>
    f.onComplete {
      case Failure(e) => if (countDownLatch.addAndGet(1) == requests.size) p.tryFailure(e)
      case Success(s) => p.trySuccess(s)
    }
  }
  p.future
}

相关内容

最新更新