我有一些像
这样的代码//all data have different types
val data1Future = loadData1(params)
val data2Future = loadData2(params)
val data3Future = loadData3(params)
def saveResult(rez): Future[_] = ???
data1Future.flatMap { data1 =>
data2Future.flatMap { data2 =>
data3Future.flatMap { data3 =>
//do some computation
//several rows and several vals
val rez = ???
saveResult(rez)
}
}
}
但它有点丑陋:)不幸的是,我不能用于理解,因为我需要像“flatYield”这样的东西
for {
data1 <- data1Future
data1 <- data1Future
data1 <- data1Future
} flatYield {
//do some computation
//several rows and several vals
val rez = data1 + data2 + data3
saveResult(rez)
}
你知道模式是如此优雅的“理解”,但在链的末尾使用flatMap而不是map?
答案 0 :(得分:3)
看起来你只想在你理解中想到另一条线,所有这些“其他计算”都应该放在另一个函数中以保持清洁:
for {
data1 <- data1Future
data2 <- data2Future
data3 <- data3Future
rez <- otherFunction(data1, data2, data3)
} yield rez
def otherFunction(d1: ?, d2: ?, d3: ?): Future[?] = {
//do some computation
//several rows and several vals
}
或者您可以使用以下内容:
(for {
data1 <- data1Future
data2 <- data2Future
data3 <- data3Future
} yield {
(data1, data2, data3)
}) flatMap { case (data1, data2, data3) =>
//do some computation
//several rows and several vals
saveResult(rez)
}
答案 1 :(得分:3)
你可以这样做:
for {
data1 <- data1Future
data2 <- data2Future
data3 <- data3Future
rez = {
//do some computation
//several rows and several vals
data1 + data2 + data3
}
r <- saveResult(rez)
} yield r
这转换为
data1Future.flatMap { data1 =>
data2Future.flatMap { data2 =>
data3Future.flatMap { data3 =>
val rez = {
//do some computation
//several rows and several vals
data1 + data2 + data3
}
saveResult(rez).map(r => r)
}
}
}
与您的代码同构。
答案 2 :(得分:0)
使用for comprehension(就像你声明的目标一样)相当于定义flatMap操作序列中的future将等到每个未来的结果然后转到下一个。由于你的期货不依赖于彼此,你可以在不等待前一个完成的情况下启动它们 - 这就是你在最初的例子中所做的。
同时启动它们并将期货存储在序列中使用Future.sequence将期货集合转换为单个Future,直到所有期货完成(或其中任何一个失败)才能完成。然后在将来完成时保存您的结果。
val data1Future = loadData1(params) //type = Future[foo]
val data2Future = loadData2(params)
val data3Future = loadData3(params)
val listOfFutures = List(data1Future,data2Future,data3Future) //type = List[Future[foo]]
val futureOfList = Future.sequence(listOfFutures) //type = Future[List[foo]]
futureOfList.onComplete( list => saveResult(list.reduce(_ + _))