Scala给自己发送消息好还是不好?

4

我正在使用json4s和play框架,有些地方我将在未来运行post/get请求,然后在成功时将响应解析为一个对象,并让actor将其发送回自己。下面是一个例子:

WS.url(authUrl).post("username=admin&password=admin") map {
  response =>
    self ! (parse(response.body) \ "body").extract[AuthObject]
}

然后在接收方法中:

case AuthObject(_, sid) => //handle authorization token

这是一种不好的做法吗?正确的方法应该是什么?我认为它的优点在于可以通过单个控制结构来处理您的演员数据流,但当然我可能在说这是一个优点的时候是错误的。


2
如果您在Actor内部有一个Future,并且该Actor具有需要在Future完成后更新的状态,则唯一安全的方法是向自身发送消息,以便重新进入Actor的上下文。在正确的情况下,这是一种有用的做法。 - cmbaxter
1
那么你的意思是这种情况下实际上最好的做法是这样的?这让人感到放心,谢谢! - JBarber
1
修复愚蠢的标签,Play FrameworkPlayback无关。 - biesior
2个回答

8

将未来的结果发送给演员的推荐方法是使用pipe模式。您的代码应如下所示:

def receive:Reveice= {
  case authUrl:String => 
    val authObjectF=WS.url(authUrl).post("username=admin&password=admin") map { response => 
      (parse(response.body) \ "body").extract[AuthObject]
    } 
    authObjectF pipeTo self
}

这被认为比map {x => self ! x }更优越的原因是错误处理。如果您不处理错误情况,它们将被简单地丢弃而没有任何提示。 使用管道模式,错误将被包装在akka.actor.Status.Failure中,并发送到目标actor(在本例中为self),以代替结果。
将future的结果传输到self是一种常见模式,可能与context.become/unbecome和stash一起使用来创建状态机。
在map/flatmap中轻易地关闭actor内部可变状态并破坏并发保证是非常容易的。如果您正在操作actors中的futures,我强烈建议您阅读此http://doc.akka.io/docs/akka/2.3.2/general/jmm.html#jmm-shared-state(如果您尚未这样做)。

1

这本质上没有什么问题。给自己发送一条消息类似于人类保留一个“待办”清单并将某些内容放在列表末尾。您的操作者最终会到达那里。而且,这真的是唯一需要考虑的问题:处理AuthObject消息的时间。如果您的应用程序只需要排序而不需要时间保证,则可以以这种方式处理它。

但是,我会谨慎对待您的\运算符,在响应体中没有“body”字段(可能是Json)的情况下返回JsError。在这种情况下,您的消息永远不会被发送,并且也不会在任何地方传递错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接