Scala在询问时关闭val

Scala在询问时关闭val,scala,akka,Scala,Akka,我想知道下面的代码是否会在map函数中的ask'callback'中关闭id值 val id = if (model.id.isEmpty) UUID.randomUUID().toString else model.id val result = couchbaseActor ? SetDoc(s"user:$id", model.toJson.compactPrint) result map { case true => sender ! Right(Success(

我想知道下面的代码是否会在map函数中的ask'callback'中关闭id值

val id = if (model.id.isEmpty) UUID.randomUUID().toString else model.id
val result = couchbaseActor ? SetDoc(s"user:$id", model.toJson.compactPrint)
   result map {
      case true => sender ! Right(Success(id))
      case false => sender ! Left(makeFailureFromErrorEnum(ErrorCode.DbSaveFailed, List("User", "Error occurred while saving to Couchbase")))
  }
谢谢,亚伦

最终解决方案:

消息处理程序:

case SaveUserReq(model) => saveDocument[User](sender, "User", model.id, model)
定义:

def saveDocument[T:JsonWriter](requester: ActorRef, prefix: String, id: String, model: T): Unit = {
  couchbaseActor ? SetDoc(s"${prefix.toLowerCase}:$id", model.toJson.compactPrint) map {
    case true => requester ! Right(Success(id))
    case false => requester ! Left(makeFailureFromErrorEnum(ErrorCode.DbSaveFailed, List(prefix, errorCouchbaseSaveFailed)))
  }
}
感谢所有帮助过你的人。

是的,应该这样做

根据闭包的定义,当我在Actor中使用Future时,sender/getSender()会消失,为什么?

“在使用将来的回调时,在actors内部,您需要小心避免关闭包含actor的引用,即不要从回调中调用方法或访问封闭actor上的可变状态。这会破坏actor封装,并可能引入同步错误和竞争条件,因为回调将被并发地调度到封闭的actor。不幸的是,目前还没有一种在编译时检测这些非法访问的方法

在Actors和JMM文档中了解更多信息”

  • 嗯,我认为id是按原样使用的。它是一个常数,不是吗

  • Victor Klang给出了错误的来源:访问
    sender
    方法
    这个演员

    val id = if (model.id.isEmpty) UUID.randomUUID().toString else model.id
    val result = couchbaseActor ? SetDoc(s"user:$id", model.toJson.compactPrint)
    result map {
      case true => this.sender.tell(Right(Success(id)), self)
      case false => this.sender.tell(Left(makeFailureFromErrorEnum(ErrorCode.DbSaveFailed, List("User", "Error occurred while saving to Couchbase"))), self)
    }
    
    它似乎关闭了
    这个

    可能以以下方式重写代码:

    val id = if (model.id.isEmpty) UUID.randomUUID().toString else model.id
    val theSender = sender
    val result = couchbaseActor ? SetDoc(s"user:$id", model.toJson.compactPrint)
    result map {
      case true => theSender ! Right(Success(id))
      case false => theSender ! Left(makeFailureFromErrorEnum(ErrorCode.DbSaveFailed, List("User", "Error occurred while saving to Couchbase")))
    }
    
    我可以帮忙


  • 为什么不简单
    if(结果)
    顺便问一下?这是一个很好的选择,但问题仍然是..我是否需要在响应中返回id,或者id val是否可以安全地在map/if部分使用?我确实喜欢map/match语法的代码样式,并保存任何类型的asInstanceOf或mapTo强制转换。我想我只是觉得这更容易理解,但我愿意接受赞成/反对的理由由于我在scala的时间还早,我还需要选择一种首选样式,您正在关闭
    模型
    ,在调用
    makeFailureFromErrorEnum
    ErrorCode
    时可能会关闭
    。此外,您正在关闭
    发送方
    ,这更糟糕,因为发送方是a
    def
    。是您的
    模型
    a
    def
    val
    var
    对象
    ?内部的
    id
    也是如此。谢谢@agilesteel,我更新了问题,因为我没有正确地
    (成功(model.id))
    。该模型是一个与接收定义匹配的案例类,匹配如下:
    case SaveUserReq(模型)=>
    。关闭发送方有什么问题吗?听起来我可能需要重构它。这是否意味着代码不安全,在调度程序处理ask响应时id值可能已更改?或者负责处理ask响应的调度程序以某种方式选择了id/状态,并且一切正常?@atom。gregg如果您使用
    val
    s并对不可变值进行操作,
    id
    的值不可能随着时间的推移而改变。换句话说,如果您坚持函数式编程实践,这是安全的。嗨,Nikita,我想在第一次调用和第二次调用之间可能会出现另一个线程/消息,因此id val将是相关的新线程的执行。我对闭包的理解需要一些工作。。提前感谢。您所指的“id”是val,因此在执行时是model.id或UUID.randomUUID()的快照。之后它不能更改。(虽然iff model.id和UUID.randomUUID都会返回一个带有apply函数的函数/对象,并且真实情况会导致执行apply,但根据时间的推移,可能会有不同的结果。但这似乎与此无关,并且您不会使用id两次)