我无法弄清楚为什么会出现错误“deadLetters
”
class MyActor extends Actor {
private def getIdList = Future { blocking(getIdListSync) }
private def getIdListSync = {
val inputStreamRaw = new URL(url).openConnection.getInputStream
val inputStream = scala.io.Source fromInputStream inputStreamRaw
val json = parse(inputStream getLines() mkString "\n")
val jsonIds = json \ "ids" \\ classOf[JInt]
jsonIds take idLimit map (_.toInt)
}
def receive = {
case Get =>
//doesn't work, the error is "sender" becomes "Actor[akka://Main/deadLetters]"
// getIdList onComplete {
// case Success(idList) =>
// sender ! Result(idList)
//
// case Failure(e) => // todo
// }
//works well
val idList = getInternalIdListSync
sender ! Result(idList)
}
}
如您所见,如果在标题为sender
的方法中使用Actor[akka://Main/deadLetters]
和Future
,则blocking
会变为getIdList
。这是为什么?我不应该使用它吗?
答案 0 :(得分:13)
问题是您在异步功能块中调用sender
。有一个简单的规则:
永远不会关闭可能异步执行的代码块中的sender方法
sender
是一个函数,它返回当前处理过的邮件的发件人。问题是,如果在sender
之类的回调中调用onComplete
,则会异步执行此回调。这意味着在此期间,参与者可以处理其他消息,因此sender
功能可能不会报告原始消息的发送者。
避免这种情况的一种方法是在执行异步代码之前将发件人存储在本地变量中:
def receive = {
case Get =>
val s = sender
// call an asynchronous function
myAsyncFunction onComplete{ result =>
s ! result
}
}
另一种方法是使用akka pipeTo
函数,如@Vadzim所指出的那样:
import akka.pattern.pipe
def receive = {
case Get =>
// call an asynchronous function
val result = myAsyncFunction
result pipeTo sender
}
有关这方面的更多信息,请参阅akka文档:http://doc.akka.io/docs/akka/snapshot/scala/futures.html#Use_With_Actors
答案 1 :(得分:5)