我想做这样的事情 -
class MyActor extends Actor {
....
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
sender ! response
}
}
}
// in some other code -
val future = myActorRef ? msg
future.onSuccess {
....
}
这会有用吗?换句话说,如果响应是在“接收”方法完成之前发回的,Akka的“请求”实现是否关注?
答案 0 :(得分:6)
是的,它会起作用,甚至还有一个内置的akka模式 - pipe
:
import akka.pattern.pipe
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
response
} pipeTo sender()
}
但是您的代码中应该注意一些注意事项:
sender
是一个函数,因此,当Future{...}
块中的代码执行时,actor可能正在处理来自其他发件人的邮件,因此您可以回复错误的发件人。为避免这种情况,请在闭包之外评估您的发件人:
val mySender = sender()
Future {
... // calculate response
mySender ! response
}
如果您使用pipe
,则无需担心此问题。
你将未来包装成一个演员并用ask
调用该演员,这再次为你提供了一个未来。如果没有演员,你应该考虑直接调用未来。
如果你真的需要演员,例如因为你要隔离一些可变状态或者消息排序很重要,你应该知道计算Future
不会发生在actor的线程上,所以你正在失去你的状态一致性和消息排序 - 另一个考虑失败的原因演员,并直接呼唤未来。
答案 1 :(得分:1)
问题是,当执行未来时,{{ joomlaComponent }}
可能不再有效。你有两个选择,这里有两个选项:
您可以在未来之前捕获 sender
:
sender
或者您可以使用 pipeTo 模式:
override def receive = {
case msg =>
.... // do something
val replyTo = sender
Future {
... // calculate response
replyTo ! response
}
}