使用 Future 的响应
Using a Future's response
希望有人可以就我遇到的这个问题的解决方案提供意见。
我会尽量简化问题,以免引入域问题等。
我有一个可选字符串列表。我正在使用 collect 方法基本上过滤掉不存在的字符串。
names collect {
case Some(value) => value
}
很简单。我打算更进一步。如果值是 None,我想调用一个函数并使用它的响应代替 None。例如
names collect {
case Some(value) => value
case _ => getData(_)
}
关键是 getData
方法 returns 一个未来。我知道期货的约定建议在回调中访问值,所以类似于 map 方法或完成,但问题是我不知道是否需要调用 getData
方法,直到我在 collect 中并具有值,所以我不能简单地将所有逻辑包装在 getData 的 map 方法中。感觉用Await不行,阻塞是个好主意
如果我能合理地处理这个问题,我将不胜感激。对 Scala 很陌生,所以我很想听听意见和选择。
编辑:
我试图简化问题,但我认为我反而错过了关键信息。
下面是我的方法的实际实现:
def calculateTracksToExport()(
implicit exportRequest: ExportRequest,
lastExportOption: Option[String]
): Future[List[String]] = {
val vendorIds = getAllFavouritedTracks().flatMap { favTracks =>
Future.sequence {
favTracks.map { track =>
musicClient.getMusicTrackDetailsExternalLinks(
track,
exportRequest.vendor.toString.toLowerCase
).map { details =>
details.data.flatMap { data =>
data.`external-links`.map { link =>
link.map(_.value).collect {
case Some(value) => value
case None => getData(track)
}
}
}.getOrElse(List())
}
}
}.map(_.flatten)
}
vendorIds
}
您可以使用 Future.sequence 来收集值:
def collect(list:List[Option[String]]):Future[List[String]] = Future.sequence(
list.map {
case Some(item) => Future.successful(item)
case _ => getData()
}
)
如果某件事可以在未来发生,你就得永远把它当作未来来对待。因此,期货序列为 return 值:
def resolve[T](input: Seq[Option[T]], supplier: => Future[T]): Seq[Future[T]] = {
input.map(option => option.map(Future.successful).getOrElse(supplier))
}
用法示例:
// Input to process
val data = Seq(Some(1), None, Some(2), None, Some(5))
//Imitates long-running background process producing data
var count = 6
def getData: Future[Int] = Future( {
Thread sleep (1000)
count += 1
count
})
resolve(data, getData) // Resolve Nones
.map(Await.result(_, 10.second)).foreach( println ) // Use result
输出:
1
8
2
7
5
希望有人可以就我遇到的这个问题的解决方案提供意见。
我会尽量简化问题,以免引入域问题等。
我有一个可选字符串列表。我正在使用 collect 方法基本上过滤掉不存在的字符串。
names collect {
case Some(value) => value
}
很简单。我打算更进一步。如果值是 None,我想调用一个函数并使用它的响应代替 None。例如
names collect {
case Some(value) => value
case _ => getData(_)
}
关键是 getData
方法 returns 一个未来。我知道期货的约定建议在回调中访问值,所以类似于 map 方法或完成,但问题是我不知道是否需要调用 getData
方法,直到我在 collect 中并具有值,所以我不能简单地将所有逻辑包装在 getData 的 map 方法中。感觉用Await不行,阻塞是个好主意
如果我能合理地处理这个问题,我将不胜感激。对 Scala 很陌生,所以我很想听听意见和选择。
编辑:
我试图简化问题,但我认为我反而错过了关键信息。
下面是我的方法的实际实现:
def calculateTracksToExport()(
implicit exportRequest: ExportRequest,
lastExportOption: Option[String]
): Future[List[String]] = {
val vendorIds = getAllFavouritedTracks().flatMap { favTracks =>
Future.sequence {
favTracks.map { track =>
musicClient.getMusicTrackDetailsExternalLinks(
track,
exportRequest.vendor.toString.toLowerCase
).map { details =>
details.data.flatMap { data =>
data.`external-links`.map { link =>
link.map(_.value).collect {
case Some(value) => value
case None => getData(track)
}
}
}.getOrElse(List())
}
}
}.map(_.flatten)
}
vendorIds
}
您可以使用 Future.sequence 来收集值:
def collect(list:List[Option[String]]):Future[List[String]] = Future.sequence(
list.map {
case Some(item) => Future.successful(item)
case _ => getData()
}
)
如果某件事可以在未来发生,你就得永远把它当作未来来对待。因此,期货序列为 return 值:
def resolve[T](input: Seq[Option[T]], supplier: => Future[T]): Seq[Future[T]] = {
input.map(option => option.map(Future.successful).getOrElse(supplier))
}
用法示例:
// Input to process
val data = Seq(Some(1), None, Some(2), None, Some(5))
//Imitates long-running background process producing data
var count = 6
def getData: Future[Int] = Future( {
Thread sleep (1000)
count += 1
count
})
resolve(data, getData) // Resolve Nones
.map(Await.result(_, 10.second)).foreach( println ) // Use result
输出:
1
8
2
7
5