我试图对不同的子角色进行异步调用,例如:
A ---> B ---> C
\---> D
Actor A向Actor B发送请求消息,B向C和D发送两条任务消息,当C和D发回结果时,B合并结果并将其发送回A。
我试图使用ask模式和onSuccess来解决这个问题:
class B(fakeInterface: String, subInterface: Array[ActorRef]) extends Actor {
val subCount = subInterface.length
var finishCount = 0
def receive = {
case reqMsg(msg) =>
if (subInterface.length == 0){
sender ! DoneMessage(msg)
} else {
implicit val timeout = Timeout(5 minutes)
val composedFutures = subInterface map { x =>
(x ? DoItMessage(msg)).mapTo[DoneMessage]
}
val allResult = Future.sequence(composedFutures)
allResult.onSuccess {
case _ => sender ! DoneMessage(msg)
}
}
}
}
但是上面的代码根本没有编译,我有三个错误:
[error] inferred type arguments [dummy.DoneMessage,Array] do not conform to method sequence's type parameter bounds [A,M[_] <: TraversableOnce[_]]
[error] val allResult = Future.sequence(composedFutures)
[error] ^
[error] type mismatch;
[error] found : Array[scala.concurrent.Future[dummy.DoneMessage]]
[error] required: M[scala.concurrent.Future[A]]
[error] val allResult = Future.sequence(composedFutures)
[error] ^
[error] Cannot construct a collection of type M[A] with elements of type A based on a collection of type M[scala.concurrent.Future[A]].
[error] val allResult = Future.sequence(composedFutures)
[error] ^
[error] three errors found
我该如何解决这个问题?或者有更合适的方法来解决这种情况吗?
答案 0 :(得分:2)
Array
不是TraversableOnce
。存在从Array
到WrappedArray
的隐式转换,它是TraversableOnce
,但是当类型参数被推断为Array
时,隐式转换为时已晚。如果将Array
替换为集合库中的一个类,例如List
您可以通过这些编译器错误。
ask模式效率低下,因为它必须为每个请求创建一个假的actor,这会产生相当大的开销。允许非演员代码与演员进行通信非常有用,但演员本身应该直接互相发送消息。演员B必须是有状态的,因此它可以跟踪来自C和D的消息,但它会带来更好的解决方案。
答案 1 :(得分:1)
scala.Array
不会从scala.collection.TraversableOnce
继承,因此无法与Future.sequence
一起使用。请尝试使用List
或Seq
。
http://www.scala-lang.org/api/current/index.html#scala.Array