喷射请求 - 仅在嵌套期货后完成请求
Spray request - Complete request only after nested futures
spray 和 scala 的新手。这几天一直在努力把它弄好。
我正在尝试将 facebook oauth2 登录 + 用户登录详细信息合并到数据库中,以防同一用户通过不同方式登录(user/pass 或 fb 登录)。
粘贴在喷雾路由片段下方。
path("facebook") {
post{
entity(as[JObject]) { json =>
val fb: FacebookAuthModel = json.extract[FacebookAuthModel]
complete {
//Get user details from fb oauth2
val fbUser = fbAuth.getIdentity(fb) match {
case Right(user: User) => user
case Left(error: Failure) => throw new FailureException(error)
}
//Check if user is already present either by fb id or email
val userFuture = userRepo(FetchUserByFacebook(fbUser.facebook.get,fbUser.email))
userFuture.map {
case u: User => {
//user present but fb id not attached yet
if (u.facebook.isEmpty) {
//update fb id for the user - fire to actor and forget, i.e no callback to sender
userRepo(UpdateFacebookId(u.id.get, fbUser.facebook.get))
}
//complete request with a token - request(1)
AuthToken(token=jwt.createToken(u))
}
case None => {
//first time user using fb login
userRepo(CreateUser(fbUser)).map {
//complete request with the token - request(2)
case createdUser: User => AuthToken(token=jwt.createToken(createdUser))
case None => throw new FailureException(Failure("Not able to CreateUser", FailureType.Unauthorized))
}
}
}
}
}
}
}
一切正常,除非用户是第一次使用 fb 登录(请参阅请求(2))。
请求在 nest future 完成之前完成,但响应为空。
我尝试对 userFuture 的结果进行平面映射,然后在其上使用 onComplete 来给出适当的响应,但它不起作用。
知道如何使用令牌成功完成请求(请求(2))吗?
如果您的代码执行路径中的两个分支之一可能导致 Future
,那么您在处理 userFuture
时必须将其编码为最小公分母。这意味着 userFuture
上的 flatMap
并在您没有明确的第二个 Future
处理的情况下使用 Future.successful
。沿着这条线:
def handleUserResult(a:Any):Future[AuthToken] = a match{
case u:User =>
if (u.facebook.isEmpty) {
userRepo(UpdateFacebookId(u.id.get, fbUser.facebook.get))
}
Future.successful(AuthToken(token=jwt.createToken(u)))
case None =>
userRepo(CreateUser(fbUser)).map {
case createdUser: User =>
AuthToken(token=jwt.createToken(createdUser))
case None =>
throw new FailureException(Failure("Not able to CreateUser", FailureType.Unauthorized))
}
}
定义该方法后,您可以按如下方式在 userResult
上使用它:
userResult.flatMap(handleUserResult)
我没有检查此代码是否存在编译问题。我更想展示 flatMap
用于处理两种情况的一般方法,一种会产生另一秒 Future
,另一种不会。
spray 和 scala 的新手。这几天一直在努力把它弄好。
我正在尝试将 facebook oauth2 登录 + 用户登录详细信息合并到数据库中,以防同一用户通过不同方式登录(user/pass 或 fb 登录)。
粘贴在喷雾路由片段下方。
path("facebook") {
post{
entity(as[JObject]) { json =>
val fb: FacebookAuthModel = json.extract[FacebookAuthModel]
complete {
//Get user details from fb oauth2
val fbUser = fbAuth.getIdentity(fb) match {
case Right(user: User) => user
case Left(error: Failure) => throw new FailureException(error)
}
//Check if user is already present either by fb id or email
val userFuture = userRepo(FetchUserByFacebook(fbUser.facebook.get,fbUser.email))
userFuture.map {
case u: User => {
//user present but fb id not attached yet
if (u.facebook.isEmpty) {
//update fb id for the user - fire to actor and forget, i.e no callback to sender
userRepo(UpdateFacebookId(u.id.get, fbUser.facebook.get))
}
//complete request with a token - request(1)
AuthToken(token=jwt.createToken(u))
}
case None => {
//first time user using fb login
userRepo(CreateUser(fbUser)).map {
//complete request with the token - request(2)
case createdUser: User => AuthToken(token=jwt.createToken(createdUser))
case None => throw new FailureException(Failure("Not able to CreateUser", FailureType.Unauthorized))
}
}
}
}
}
}
}
一切正常,除非用户是第一次使用 fb 登录(请参阅请求(2))。
请求在 nest future 完成之前完成,但响应为空。
我尝试对 userFuture 的结果进行平面映射,然后在其上使用 onComplete 来给出适当的响应,但它不起作用。
知道如何使用令牌成功完成请求(请求(2))吗?
如果您的代码执行路径中的两个分支之一可能导致 Future
,那么您在处理 userFuture
时必须将其编码为最小公分母。这意味着 userFuture
上的 flatMap
并在您没有明确的第二个 Future
处理的情况下使用 Future.successful
。沿着这条线:
def handleUserResult(a:Any):Future[AuthToken] = a match{
case u:User =>
if (u.facebook.isEmpty) {
userRepo(UpdateFacebookId(u.id.get, fbUser.facebook.get))
}
Future.successful(AuthToken(token=jwt.createToken(u)))
case None =>
userRepo(CreateUser(fbUser)).map {
case createdUser: User =>
AuthToken(token=jwt.createToken(createdUser))
case None =>
throw new FailureException(Failure("Not able to CreateUser", FailureType.Unauthorized))
}
}
定义该方法后,您可以按如下方式在 userResult
上使用它:
userResult.flatMap(handleUserResult)
我没有检查此代码是否存在编译问题。我更想展示 flatMap
用于处理两种情况的一般方法,一种会产生另一秒 Future
,另一种不会。