【问题标题】:Error on a method that return a Future[Option[BasicProfile]]返回 Future[Option[BasicProfile]] 的方法出错
【发布时间】:2014-09-22 12:35:00
【问题描述】:

我正在使用 SecureSocial(主版本)编写一个 Play 2.3 应用程序。 我在我的系统中创建了一个代表用户数据的 LoginUser。

/**
 * Class representing a User in the system.
 * @constructor Create a new LoginUser instance from a BasicProfile object.
 * @param profile represents the BasicProfile object associated with the user.
 */
case class LoginUser(val profile: BasicProfile)

现在我正在尝试实现(SecureSocial 的)UserService[T] 特征,但我遇到了麻烦。

/**
 * Class tha handle all the request for read/write user data in/from the database.
 */
class InMemoryUserService extends UserService[LoginUser] {

  private var tokens = Map[String, MailToken]()
  /**
   * Finds a user by provider id and user id.
   * @param providerId - the user provider id.
   * @param userId - the user user id.
   * @return an optional user
   */
  def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
    val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
    future onComplete {
      case Success(Some(x)) => return x.profile
      case _ => None
    }
}

find 方法返回一个 Future[Option[BasicProfile]] 对象,但编译器告诉我代码不正确。 这里是编译器的输出:

[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:68: type mismatch;
[error]  found   : securesocial.core.BasicProfile
[error]  required: scala.concurrent.Future[Option[securesocial.core.BasicProfile]]
[error]       case Success(Some(x)) => return x.profile

怎么了?? 我该如何解决我的问题??

【问题讨论】:

    标签: scala securesocial


    【解决方案1】:

    您不应通过onComplete 在您的Future 上注册回调。相反,你想map内容来改变类型:

    def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
        val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
    
        future map {
          case Some(x) => Some(x.profile)
          case None => None
        }
    }
    

    这应该使编译愉快:) 注意onComplete 的返回类型是Unit,而使用map 我可以对Future 的内容进行任何更改。

    maps FutureOption 的简洁版本:

    def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
        val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
    
        future.map(_.map(_.profile)
    }
    

    【讨论】:

    • 谢谢。但是您发布的第一个代码没有编译给我。这里的编译器错误:[错误] /Users/alberto/git/recommendation-system/app/security/UserService.scala:87:构造函数无法实例化为预期类型; [error] found : Some[A] [error] required: scala.concurrent.Future[Option[security.LoginUser]] [error] case Some(x) => Some(x.profile)
    • @albertoadami ha,对此感到抱歉,忘记拨打map :) 已修复。我认为你应该喜欢第二种形式,更简单,更惯用。我认为case Some(x) => Some(x.profile) 非常丑陋,我只是发布它以强调唯一真正的区别是调用map 而不是onComplete
    猜你喜欢
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2015-11-03
    • 2016-11-08
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    相关资源
    最近更新 更多