使用 for-comp 处理期货,但如果条款使事情变得困难
Handling futures with for-comp, but if clauses are making things difficult
我发现我 运行 进入了下面的模式分配,但我无法让它工作或看起来不错的风格。
我有一个理解是 return Futures,然后我构建我的模型以在视图中显示。但是在我 return 我的操作中的结果之前,我有时不得不使用 if 子句进行分支并可能加载更多数据。
下面的代码目前无法编译,你建议我怎么做才能让下面的代码遵循这种模式的正确风格?
它无法编译,因为 compr 的内部是 return 一个 Future[Option[Something]] 但我已经将 c 定义为 Option[Something]
for {
a <- fooService.getA()
b <- fooService.getB()
} yield {
var c: Option[Something] = None
if(a.size > 0) {
c = for {
c <- fooService.getC()
} yield {
Some(c)
}
}
}
val model = FooModel(a, b, c)
Ok(views.html.foo.show(model))
我的视图模型定义为:
FooModel(a: A, b: B, c: Option[Something])
这看起来相当清楚:
for {
a <- fooService.getA()
b <- fooService.getB()
c <- if (a.nonEmpty) fooService.getC() else Future.successful(None)
} yield {
val model = FooModel(a, b, c)
Ok(views.html.foo.show(model))
}
如果需要,将 if (a.nonEmpty) fooService.getC() else Future.successful(None)
提取到另一个方法或服务。
现在可以编译了,但是你有没有注意到,你的程序是顺序运行的?
object fooService{
def getA() = {
Future{
println("I'm getA")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"A"
}
}
def getB() = {
Future{
println("I'm getB")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"B"
}
}
}
object Main {
def main(args: Array[String]) ={
for {
a <- fooService.getA()
b <- fooService.getB()
} println(a + b)
Thread.sleep(4000)
}
}
这是输出:
I'm getA
.
.
.
.
.
.
.
.
.
.
I'm getB
.
.
.
.
.
.
.
.
.
.
AB
稍作改动:
object fooService{
def getA() = {
Future{
println("I'm getA")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"A"
}
}
def getB() = {
Future{
println("I'm getB")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"B"
}
}
}
object Main {
def main(args: Array[String]) ={
val f1 = fooService.getA()
val f2 = fooService.getB()
for {
a <- f1
b <- f2
} println(a + b)
Thread.sleep(4000)
}
}
输出:
I'm getA
I'm getB
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
AB
我发现我 运行 进入了下面的模式分配,但我无法让它工作或看起来不错的风格。
我有一个理解是 return Futures,然后我构建我的模型以在视图中显示。但是在我 return 我的操作中的结果之前,我有时不得不使用 if 子句进行分支并可能加载更多数据。
下面的代码目前无法编译,你建议我怎么做才能让下面的代码遵循这种模式的正确风格?
它无法编译,因为 compr 的内部是 return 一个 Future[Option[Something]] 但我已经将 c 定义为 Option[Something]
for {
a <- fooService.getA()
b <- fooService.getB()
} yield {
var c: Option[Something] = None
if(a.size > 0) {
c = for {
c <- fooService.getC()
} yield {
Some(c)
}
}
}
val model = FooModel(a, b, c)
Ok(views.html.foo.show(model))
我的视图模型定义为:
FooModel(a: A, b: B, c: Option[Something])
这看起来相当清楚:
for {
a <- fooService.getA()
b <- fooService.getB()
c <- if (a.nonEmpty) fooService.getC() else Future.successful(None)
} yield {
val model = FooModel(a, b, c)
Ok(views.html.foo.show(model))
}
如果需要,将 if (a.nonEmpty) fooService.getC() else Future.successful(None)
提取到另一个方法或服务。
现在可以编译了,但是你有没有注意到,你的程序是顺序运行的?
object fooService{
def getA() = {
Future{
println("I'm getA")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"A"
}
}
def getB() = {
Future{
println("I'm getB")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"B"
}
}
}
object Main {
def main(args: Array[String]) ={
for {
a <- fooService.getA()
b <- fooService.getB()
} println(a + b)
Thread.sleep(4000)
}
}
这是输出:
I'm getA
.
.
.
.
.
.
.
.
.
.
I'm getB
.
.
.
.
.
.
.
.
.
.
AB
稍作改动:
object fooService{
def getA() = {
Future{
println("I'm getA")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"A"
}
}
def getB() = {
Future{
println("I'm getB")
for(i <- 1 to 10){
println(".")
Thread.sleep(200)
}
"B"
}
}
}
object Main {
def main(args: Array[String]) ={
val f1 = fooService.getA()
val f2 = fooService.getB()
for {
a <- f1
b <- f2
} println(a + b)
Thread.sleep(4000)
}
}
输出:
I'm getA
I'm getB
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
AB