使用Future的回复

时间:2015-12-18 15:00:57

标签: scala future

希望有人可以就我遇到的这个问题找到解决方案的意见。

我会尝试简化问题,以免引起域名问题等。

我有一个可选字符串列表。我正在使用collect方法基本上过滤掉不存在的字符串。

names collect {
    case Some(value) => value
}

足够简单。我正在寻找实际的进一步。如果值是None,我想调用一个函数并使用它的响应来代替None。例如

names collect {
    case Some(value) => value
    case _ => getData(_)
}

catch是getData方法返回未来。我理解期货的约定建议在回调中访问值,所以像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
}

2 个答案:

答案 0 :(得分:1)

您可以使用Future.sequence收集值:

def collect(list:List[Option[String]]):Future[List[String]] = Future.sequence(
  list.map {
    case Some(item) => Future.successful(item)
    case _ => getData()
  }
)

答案 1 :(得分:0)

如果将来有什么东西,你将不得不像将来一样对待它。因此,将期货序列作为回报值:

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

http://ideone.com/aa8nJ9