2014-09-22 34 views
0

我正在使用SecureSocial(主版本)編寫Play 2.3應用程序。 我已經創建了一個表示我的系統中的用戶數據的LoginUser。返回Future的方法的錯誤[Option [BasicProfile]]

/** 
* 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) 

現在我試圖實現UserService [T]特質(SecureSocial的),但我有麻煩。

/** 
* 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 

怎麼回事? 我該如何解決我的問題?

回答

4

您不應通過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

一個更簡潔的版本,map小號兩種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) 
} 
+0

感謝。但是,你的第一個代碼沒有編譯給我。 這裏的編譯器錯誤:[error] /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) – 2014-09-22 12:57:46

+0

@albertoadami ha ,對不起,忘記了調用'map' :)修復。我認爲你應該喜歡第二種形式,但更簡單,更習慣。 'case Some(x)=> Some(x.profile)'是非常難看的,我想我只是發佈它來強調唯一真正的區別是調用'map'而不是'onComplete'。 – vptheron 2014-09-22 13:14:07