I have the following method that does some handling with Future
s:
def registerNewUser(user: User): Future[Either[ServiceError, User]] = async {
val encryptedUser =
user.copy(encrypt(user))
def checkResultAndFetchUser(result: WriteResult, encryptedEmail: String): Future[Either[ServiceError, User]] = {
if (result.hasErrors)
Future.successful(Left(ServiceError(result.writeErrors.map(_.errmsg).toString)))
else
userByEmail(encryptedEmail)
}
def handleInsertError(result: WriteResult): Either[ServiceError, User] = {
if (result.code contains 11000)
Left(ServiceError("Email already exists"))
else
Left(ServiceError(result.writeErrors.map(_.errmsg).toString))
}
val result = userCollection.insert(encryptedUser).map( writeRes =>
checkResultAndFetchUser(writeRes, encryptedUser.email)
).recover {
case res: WriteResult => Future.successful(handleInsertError(res))
}
await(result.flatMap(fut => fut))
}
Here are my questions:
The encryptedUser
local variable is being used in the checkResultAndFetchUser
method, the userCollection.insert(encryptedUser)
returns a Future
, so is there any chance that another encryptedUser
might be captured in the checkResultAndFetchUser
method? That would mean, I'm doomed!
Is this a good way of dealing with Future
s and its handling?
I'm not exactly sure what you mean with your first question, but there is only one encryptedUser
value, so even though both functions return a Future
they both use the same encryptedUser
.
For handling you Future
s :
await
on the "result" Future
. You are using map
on userCollection.insert()
and then using result.flatMap(fut => fut)
, which can be simplified to using flatMap
directly.
userCollection.insert(encryptedUser).flatMap( writeRes => checkResultAndFetchUser(writeRes, encryptedUser.email) )
Which could also be written as a for comprehension.
The end result could look like :
def registerNewUser(user: User): Future[Either[ServiceError, User]] = {
def checkResultAndFetchUser(result: WriteResult, encryptedEmail: String) = ???
def handleInsertError(result: WriteResult) = ???
def insertUser(user: User): WriteResult =
userCollection.insert(user).recover {
case res: WriteResult => handleInsertError(res)
}
val encryptedUser = user.copy(encrypt(user))
for {
writeRes <- insertUser(encryptedUser)
user <- checkResultAndFetchUser(writeRes, encryptedUser.email)
} yield user
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.