处理Scala中的闭包和期货

时间:2015-10-25 06:25:11

标签: scala closures future

我有以下方法对Future s进行一些处理:

def registerNewUser(user: User): Future[Either[ServiceError, User]] = async {
  val encryptedUser =
    user.copy(encrypt(user))

  def checkResultAndFetchUser(result: WriteResult, encryptedEmail: String): Future[Either[ServiceError, User]] = {
    if (result.hasErrors)
      Future.successful(Left(ServiceError(result.writeErrors.map(_.errmsg).toString)))
    else
      userByEmail(encryptedEmail)
  }

  def handleInsertError(result: WriteResult): Either[ServiceError, User] = {
    if (result.code contains 11000)
      Left(ServiceError("Email already exists"))
    else
      Left(ServiceError(result.writeErrors.map(_.errmsg).toString))
  }

  val result = userCollection.insert(encryptedUser).map( writeRes =>
    checkResultAndFetchUser(writeRes, encryptedUser.email)
  ).recover {
    case res: WriteResult => Future.successful(handleInsertError(res))
  }

  await(result.flatMap(fut => fut))
}

以下是我的问题:

  1. encryptedUser方法正在使用checkResultAndFetchUser局部变量,userCollection.insert(encryptedUser)会返回Future,所以有可能是另一个encryptedUser可能会在checkResultAndFetchUser方法中捕获?那就意味着,我注定了!

  2. 这是处理Future及其处理的好方法吗?

1 个答案:

答案 0 :(得分:1)

我不确定你对第一个问题的意思,但只有一个encryptedUser值,所以即使两个函数都返回Future,它们都使用相同的encryptedUser }。

为了处理你Future s:

  • 您实际上并没有使用async / await,因为您只在“结果”await上使用Future
  • 您在map上使用userCollection.insert(),然后使用result.flatMap(fut => fut),可以将其简化为直接使用flatMap

    userCollection.insert(encryptedUser).flatMap( writeRes =>
      checkResultAndFetchUser(writeRes, encryptedUser.email)
    )
    
  • 也可以写成为理解。

最终结果可能如下:

def registerNewUser(user: User): Future[Either[ServiceError, User]] = { 
  def checkResultAndFetchUser(result: WriteResult, encryptedEmail: String) = ???

  def handleInsertError(result: WriteResult) = ???

  def insertUser(user: User): WriteResult =
    userCollection.insert(user).recover {
      case res: WriteResult => handleInsertError(res)
    }

  val encryptedUser = user.copy(encrypt(user))

  for {
    writeRes <- insertUser(encryptedUser)
    user     <- checkResultAndFetchUser(writeRes, encryptedUser.email)
  } yield user
}