如何在使用期货时避免Scala中的Await.ready?

时间:2018-01-19 09:47:28

标签: scala future

我有以下伪代码。 按顺序调用fetchfetchRecordDetailuploadnotifyUploaded函数。每个函数都返回一个future事件,但是第一个函数返回Option [T],前进(fetchRecordDetailuploadnotifyUploaded)调用我只需携带Some [T]类型并忽略没有。

不幸的是,我能够通过太多Await.ready次呼叫来实现以下输出。

预期输出

通知列表(UploadResult(a_detail_uploaded),UploadResult(c_detail_uploaded))

代码

def fetch(id: String): Future[Option[Record]] = Future {
    Thread sleep 100
    if (id != "b" && id != "d") {
        Some(Record(id))
    } else None
}

def fetchRecordDetail(record: Record): Future[RecordDetail] = Future {
    Thread sleep 100
    RecordDetail(record.id + "_detail")
}

def upload(recordDetail: RecordDetail): Future[UploadResult] = Future {
    Thread sleep 100
    UploadResult(recordDetail.id + "_uploaded")
}

def notifyUploaded(results: Seq[UploadResult]): Future[Unit] = Future{ println("notified " + results)}

   val result: Future[Unit] = //Final call to 'notifyUploaded' goes here

    Await.ready(result, Duration.Inf)

有人可以通过避免Await.ready电话来帮助改进此代码。

val ids: Seq[String] = Seq("a", "b", "c", "d")
def filterSome(s:String) = fetch(s) map ((s, _)) collect { case (s, Some(v)) => v }
val validData = ids map filterSome
Await.ready(Future.sequence(validData), Duration.Inf)
val records = validData.map(_.value.get.toOption)
val recordDetails = records.flatten map fetchRecordDetail
Await.ready(Future.sequence(recordDetails), Duration.Inf)
val uploadResult = recordDetails.map(_.value.get.toOption).flatten  map upload
Await.ready(Future.sequence(uploadResult), Duration.Inf)
val seqUploadResult = uploadResult.map(_.value.get.toOption)
val result: Future[Unit] =  notifyUploaded(seqUploadResult.flatten)
Await.ready(result, Duration.Inf)

2 个答案:

答案 0 :(得分:2)

这样的东西是你想要的?:

  for {
    f1 <- validData
    f2 <- recordDetails
    f3 <- seqUploadResult
  }yield f3
  onComplete(notifyUploaded(seqUploadResult.flatten))

答案 1 :(得分:2)

这似乎有效。

Future.sequence(ids.map(fetch))                             //fetch Recs
  .map(_.flatten)                                           //remove None
  .flatMap(rs=> Future.sequence(rs.map(fetchRecordDetail))) //fetch Details
  .flatMap(ds=> Future.sequence(ds.map(upload)))            //upload
  .flatMap(notifyUploaded)                                  //notify

它会返回{<1}}您 Future[Unit],但我不知道原因。