在 Scala 中处理闭包和期货
Dealing with Closures and Futures in Scala
我有以下方法对 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))
}
这是我的问题:
在checkResultAndFetchUser
方法中使用了encryptedUser
局部变量,userCollection.insert(encryptedUser)
returns一个Future
,也是有没有可能在 checkResultAndFetchUser
方法中捕获另一个 encryptedUser
?那就意味着,我在劫难逃!
这是处理 Future
及其处理的好方法吗?
我不太确定你的第一个问题是什么意思,但只有一个 encryptedUser
值,所以即使两个函数 return 和 Future
它们都使用同样的 encryptedUser
.
为了处理你 Future
s :
- 您并没有真正使用 async / await,因为您只在 "result"
Future
. 上使用 await
你在userCollection.insert()
上使用map
,然后使用result.flatMap(fut => fut)
,可以简化为直接使用flatMap
。
userCollection.insert(encryptedUser).flatMap( writeRes =>
checkResultAndFetchUser(writeRes, encryptedUser.email)
)
也可以写成for comprehension
最终结果可能如下所示:
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
}
我有以下方法对 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))
}
这是我的问题:
在
checkResultAndFetchUser
方法中使用了encryptedUser
局部变量,userCollection.insert(encryptedUser)
returns一个Future
,也是有没有可能在checkResultAndFetchUser
方法中捕获另一个encryptedUser
?那就意味着,我在劫难逃!这是处理
Future
及其处理的好方法吗?
我不太确定你的第一个问题是什么意思,但只有一个 encryptedUser
值,所以即使两个函数 return 和 Future
它们都使用同样的 encryptedUser
.
为了处理你 Future
s :
- 您并没有真正使用 async / await,因为您只在 "result"
Future
. 上使用 你在
userCollection.insert()
上使用map
,然后使用result.flatMap(fut => fut)
,可以简化为直接使用flatMap
。userCollection.insert(encryptedUser).flatMap( writeRes => checkResultAndFetchUser(writeRes, encryptedUser.email) )
也可以写成for comprehension
await
最终结果可能如下所示:
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
}