簡體   English   中英

在Scala中處理future [Ething]類型

[英]Dealing with Future[Either] Types in Scala

我有點難以使它結構化。 這是我想要做的:

def checkResultAndFetchUser(result: WriteResult, encryptedEmail: String): Future[Either[ServiceError, User]] = Future {
  if (result.code contains 11000)
    Left(ServiceError("Email already exists"))
  else if (result.hasErrors)
    Left(ServiceError(result.writeErrors.map(_.errmsg).toString))
  else
    userByEmail(encryptedEmail).map(user =>
      user
    ).recover {
      case NonFatal(ex) => Left(ServiceError(ex.getMessage))
    }
}

checkResultAndFetchUser(
  await(userCollection.insert(encryptedUser)), encryptedUser.email
)

我期望checkResultAndFetchUser返回Future[Either[ServiceError, User]] ,但是我看到了以下編譯器失敗:

Error:(155, 28) type mismatch;
 found   : scala.concurrent.Future[Either[DBService.this.ServiceError,com.inland.model.User]]
 required: Either[DBService.this.ServiceError,com.inland.model.User]
Error occurred in an application involving default arguments.
    checkResultAndFetchUser(
                           ^
Error:(150, 19) type mismatch;
 found   : scala.concurrent.Future[Either[DBService.this.ServiceError,com.inland.model.User]]
 required: Either[DBService.this.ServiceError,com.inland.model.User]
        ).recover {
                  ^

正如我所期望的那樣, userByEmail(encryptedEmail)方法為我提供了Future[Either[ServiceError, User]] ,但問題出在哪里?

編輯:我找到了一個解決方案:

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

await(checkResultAndFetchUser(
  await(userCollection.insert(encryptedUser)), encryptedUser.email
))

這樣可以嗎? 我的意思是,實現是安全的,因為我正在使用局部變量返回Future

就可以產生預期結果的意義而言,您的代碼是可以的。 但是,正如@Łukasz在評論中提到的那樣,這樣做有點浪費。

原因是,每當您這樣實例化Future時,都會產生一個新任務,該任務需要在某個ExecutionContext上進行調度。 通常,每當您只需要將已計算的結果包裝在Future中時(或者如果計算速度非常快),最好使用Future.successful以避免開銷。

這是我修改checkResultAndFetchUser函數的方法:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM