具有Future返回类型的函数始终返回None

时间:2016-07-28 17:08:16

标签: scala playframework

我有以下功能:

//retrieves record from database
def getAll: Future[List[User]] = {
  try {
    Logger.info("Getting all user record.")
    db.run(userTableQuery.to[List].result)
  }
  catch {
    case ex: Exception => Logger.error("Exception in getting all user record. " + ex)
      Future {
        List[User]()
      }
  }
}


//checks whethe the email exist in list or not
def checkEmail(email : String): Future[Option[User]] ={
  /* userRepo.getAll.map(userList => userList.filter(user => user.email == email).map { value => println(value)
     userList
   })*/
  userRepo.getAll.map(userList => userList.filter(user => user.email == email).headOption)

}


//allows to sign in and redirects to dashboard
def signIn() = {
  Logger.debug("signingIn in progress. ")
  loginForm.bindFromRequest.fold(
    formWithErrors => {
      Logger.error("Sign-In badRequest.")
      Future(BadRequest(views.html.home(webJarAssets, formWithErrors, signUpForm)))
    },
    validData => {
      userService.checkEmail(validData.email).map(value => {
        value match {
          case Some(us) =>Redirect(routes.HomeController.homePage).flashing("ERROR" -> "User  exist")
          case None => Redirect(routes.HomeController.homePage).flashing("ERROR" -> "User doesn't exist")
        }
      }
      )
    }
  )
}

但是当我致电signin()时,它始终会返回None

我使用了一些调试器代码,我猜filter()内的checkMail()无法正常工作。 但是getall()正常工作并在数据库中提供所有记录。

2 个答案:

答案 0 :(得分:0)

我认为问题在于如何将用户电子邮件与checkMail()函数中过滤器内提供的用户电子邮件进行比较。 字符串相等有点棘手,如果你使用==比较它们,你比较对象而不是值,所以你应该使用.equals()来比较值。 您可以阅读有关此blog post

的更多信息

尝试像这样重写checkMail():

  def checkEmail(email : String): Future[Option[User]] ={
      userRepo.getAll.map(userList => userList.filter(user => user.email.equals( email ) ).headOption)
  }

您还可以使用find()简化.filter()e .headOption,它只在一个命令中执行相同的操作。你可以像这样重写它:

  def checkEmail(email : String): Future[Option[User]] ={
      userRepo.getAll.map(userList => userList.find(user => user.email.equals( email ) ) )
  }

答案 1 :(得分:0)

您可以在checkmail下使用find方法,而不是使用过滤器。此外,由于这是scala,您正确使用“==”,请参阅博客here

我希望这段代码可以修复:

//checks whethe the email exist in list or not
def checkEmail(email : String): Future[Option[User]] ={
  /* userRepo.getAll.map(userList => userList.filter(user => user.email == email).map { value => println(value)
     userList
   })*/
  userRepo.getAll.map(userList => userList.find(user => user.email == email))

}

我尝试使用终端直接模拟/试验您的实施:

scala> case class User(email: String)
defined class User

scala> import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.ExecutionContext.Implicits.global

scala> val allUser = scala.concurrent.Future {List(User("carl@test.com"), User("los@test.com"), User("pos@test.com"))}
allUser: scala.concurrent.Future[List[User]] = scala.concurrent.impl.Promise$DefaultPromise@751d3241

scala> val checkmail = allUser.map(userlist=>userlist.find(user=>user.email == "carl@test.com"))
checkmail: scala.concurrent.Future[Option[User]] = scala.concurrent.impl.Promise$DefaultPromise@1358b28e

scala> val rslt = checkmail.map(value => value match {case Some(x) =>println(x); x.email case None => println("None"); "nothing" })
rslt: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@18324f97
User(carl@test.com)

scala> import scala.concurrent.duration._
import scala.concurrent.duration._


scala> import scala.concurrent._
import scala.concurrent._

scala> Await.result(rslt, 3 seconds)
warning: there was one feature warning; re-run with -feature for details
res8: String = carl@test.com