我有一个现有的 API
返回 Future
.现在推出 Actor
对于其中一个用例并尝试继续使用相同的服务 API
从中。从下面你可以看到MyService.saveValues
回归 future 。
object MyActor {
implicit val ec = scala.concurrent.ExecutionContext.Implicits.global
implicit val timeout = Timeout(1 second)
case class SampleMessage(list: List[String])
val actorSystem = //get actorSystem that was created at the startup
def saveMessage(list: List[String]) ={
val res = (actorSystem.actorOf(Props[MyActor]) ? SaveMyMessage(list) ).mapTo[Future[\/[Throwable,String]]
//res map{ r=>
//}
}
}
class MyActor extends Actor {
import MyActor._
def receive = {
case SaveMyMessage(list) =>
val originalSender = sender
val res : Future[\/[Throwable,String] ] = MyService.saveValues(list)
originalSender ! res
}
}
正如您在
def saveMessage
中看到的那样我正在使用 ask
等待 Actor 的结果。然而ask
也创造了自己的 future ,所以结果( val res
)在 saveMessage
变成 Future[Future[T]]
这看起来很烦人。处理这种情况的最佳方法是什么?
最佳答案
pipeTo
将 Future 的结果转发到 ActorRef
.
import akka.pattern.pipe
val originalSender = sender
val res : Future[\/[Throwable,String] ] = MyService.saveValues(list)
res pipeTo originalSender
如
saveValues
抛出,你的 future 永远不会完成,但最终会超时。如果你最终得到
Future[Future[A]]
,但想要 Future[A]
由于 sequencing/traversing
或者别的什么,你总是可以“flatMap那个狗屎”。import ExecutionContext.Implicits.global
val foo: Future[Future[Int]] = ???
val bar: Future[Int] = foo.flatMap(identity)
如果您已经依赖 scalaz(如果在 scalaz 7.0.x 上,则使用 scalaz.contrib),您可以使用
join
在 monad 语法中定义。import scalaz.syntax.monad._
import scalaz.contrib.std.scalaFuture._
val bar2: Future[Int] = foo.join
关于scala - 返回来自 Actor 的 future 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24618738/