我的服务正在返回Future [Option [Entity]],我目前正在这样做:
val user = userService.getById(1)
val company = userService.getById(1)
if(user.get.companyId == company.get.id) {
save(...)
if(...) {
blahService.boo();
}
return ...
} else
{
...
return ...
}
现在,如果我将其重构为for-comprehension,我该如何处理else子句?我是否从for-comp返回一些东西,然后像其他'那样使用它?条款?
另外,如何从for compr中删除.get?
for {
userOption <- userService.getById(1)
companyOption <- cService.getById(2)
if (userOption.get.companyId == companyOption.get.id)
} {
..
..
saveUser(userOption.get, companyOption.get)
return ..
}
答案 0 :(得分:2)
以下是使用Scalaz OptionT
的解决方案:
import scalaz.OptionT.optionT
(for {
user <- optionT(userService.getById(1))
company <- optionT(cService.getById(2))
if (user.companyId == company.id)
} yield {
saveUser(user, company)
}).run
参见例如这个讨论更多:http://loicdescotte.github.io/posts/scala-compose-option-future/
答案 1 :(得分:1)
在将Future
与控制流混合时,我强烈推荐scala-async。我发现它几乎严格地优于map
或for
- 对Future
s的理解。您可以使用哪种控制流结构存在一些限制,但对于您的情况,它会很有效:
async {
val userOption = await(userService.getById(1))
val companyOption = await(cService.getById(2))
(userOption, companyOption) match {
case (Some(user), Some(company)) => // happy path
case _ => // sad path
}
}
整个async {...}
块的类型为Future[A]
,其中A
由match
的分支决定。
答案 2 :(得分:0)
如果您被限制为香草Scala,
val x = for {
userOption <- userService.getById(1)
companyOption <- cService.getById(2)
} yield {
for {
user <- userOption
company <- companyOption
} yield {
if (user.id == company.id) { ... }
else { ... }
}
}
x
然后就这么简单。
请注意,如果两个调用之一返回Future
,则生成的Failure
将失败。此外,如果其中一个调用返回Option
,则生成的None
将为None
。这种理解基本上只适用于&#34;快乐的道路&#34;代码,并且可能不足以满足每个不同分支需要采取不同操作的情况。