gpt4 book ai didi

Scala 对 future 和期权的理解

转载 作者:行者123 更新时间:2023-12-04 13:57:51 24 4
gpt4 key购买 nike

我最近读了曼努埃尔伯恩哈特的新书Reactive Web Applications .在他的书中,他指出 Scala 开发人员应该从不 使用 .get检索可选值。

我想接受他的建议,但我正在努力避免.get用于理解 Futures 时。

假设我有以下代码:

for {
avatarUrl <- avatarService.retrieve(email)
user <- accountService.save(Account(profiles = List(profile.copy(avatarUrl = avatarUrl)))
userId <- user.id
_ <- accountTokenService.save(AccountToken.create(userId, email))
} yield {
Logger.info("Foo bar")
}

通常,我会使用 AccountToken.create(user.id.get, email)而不是 AccountToken.create(userId, email) .但是,当试图避免这种不良做法时,我收到以下异常:
[error]  found   : Option[Nothing]
[error] required: scala.concurrent.Future[?]
[error] userId <- user.id
[error] ^

我该如何解决这个问题?

最佳答案

第一个选项

如果你真的想用for理解你必须把它分成几个for s,其中每个都使用相同的 monad 类型:

for {
avatarUrl <- avatarService.retrieve(email)
user <- accountService.save(Account(profiles = List(profile.copy(avatarUrl = avatarUrl)))
} yield for {
userId <- user.id
} yield for {
_ <- accountTokenService.save(AccountToken.create(userId, email))
}

第二种选择

另一种选择是避免 Future[Option[T]]一共使用 Future[T]可以变成 Failure(e)哪里 eNoSuchElementException每当您期待 None (在您的情况下,是 accountService.save() 方法):
def saveWithoutOption(account: Account): Future[User] = {
this.save(account) map { userOpt =>
userOpt.getOrElse(throw new NoSuchElementException)
}
}

那么你将拥有:
(for {
avatarUrl <- avatarService.retrieve(email)
user <- accountService.saveWithoutOption(Account(profiles = List(profile.copy(avatarUrl = avatarUrl)))
_ <- accountTokenService.save(AccountToken.create(user.id, email))
} yield {
Logger.info("Foo bar")
}) recover {
case t: NoSuchElementException => Logger.error("boo")
}

第三个选项

回退到 map/ flatMap并介绍中间结果。

关于Scala 对 future 和期权的理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39530213/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com