我需要Scala Futures和Promises的帮助。我试图从雅虎提取历史数据。我写了一个函数,它接受货币字符串以及开始和结束日期。
def getccyHistory(ccy: String, startDate: String, endDate: String): Future[List[HistoricalCurrency]] = Future {
val init = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22"
val first = "%3DX%22%20and%20startDate%20%3D%20%22"
val end = "%22%20and%20endDate%20%3D%20%22"
val last = "%22&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
val finalString = init + ccy + first + startDate + end + endDate + last
val histccy = XML.loadString(Source.fromURL(new URL(finalString)).mkString)
println ("I am in currency {}", ccy)
(histccy \ "results" \ "quote") map {x =>
HistoricalCurrency(
"JPY", (x \ "Date").text, (x \ "Open").text ,(x \ "High").text,
(x \ "Low").text, (x \ "Close").text)
}.toList
}
以下是货币清单,我想同时获取这些货币的历史记录。当我尝试运行期货时,我得到了承诺列表,我不知道如何提取。我对Scala Futures和Promises有read quite a bit。
val a = List("DKK","JPY","BRL","GBP", "EUR", "SEK")
我附上完整的代码以便于理解。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.promise
import scala.xml._
import java.net._
import scala.io.Source
import scala.util.{Success, Failure}
case class HistoricalCurrency(
val ccy : String,
val Date : String,
val Open : String,
val High : String,
val Low : String,
val Close : String)
def getccyHistory(ccy: String, startDate: String, endDate: String): Future[List[HistoricalCurrency]] = Future {
val init = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22"
val first = "%3DX%22%20and%20startDate%20%3D%20%22"
val end = "%22%20and%20endDate%20%3D%20%22"
val last = "%22&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
val finalString = init + ccy + first + startDate + end + endDate + last
val histccy = XML.loadString(Source.fromURL(new URL(finalString)).mkString)
println ("I am in currency {}", ccy)
(histccy \ "results" \ "quote") map {x =>
HistoricalCurrency(
"JPY", (x \ "Date").text, (x \ "Open").text ,(x \ "High").text,
(x \ "Low").text, (x \ "Close").text)
}.toList
}
val a = List("DKK","JPY","BRL","GBP", "EUR", "SEK")
val f = a map {x => getccyHistory(x,"2015-07-12","2016-01-11") }
//> f : List[scala.concurrent.Future[List[Samples.FutureTest.HistoricalCurrenc
//| y]]] = List(scala.concurrent.impl.Promise$DefaultPromise@306cd243, scala.co
//| ncurrent.impl.Promise$DefaultPromise@3860458b, scala.concurrent.impl.Promis
//| e$DefaultPromise@3875c597, scala.concurrent.impl.Promise$DefaultPromise@3bf
//| f5976, scala.concurrent.impl.Promise$DefaultPromise@794a70bf, scala.concurr
//| ent.impl.Promise$DefaultPromise@63049cf)
f map {x => x.onComplete { case Success(value) => println("Hello")
}
}
答案 0 :(得分:1)
您可以使用Future.traverse
。这将执行一个函数,为列表(或其他集合)中的每个项目返回Future
,并将结果合并为一个Future
。
对于您的货币清单,这将给您:
val getForCurrency: String => Future[List[HistoricalCurrency]] =
getccyHistory(_, "2015-07-12","2016-01-11")
Future.traverse(a)(getForCurrency)
// scala.concurrent.Future[List[List[HistoricalCurrency]]]
然后您只有一个Future
而不是List[Future[...]]
。
您可以使用List[Future[...]]
将收到的Future.sequence
转换为相同的结果,但traverse
只需一步即可完成映射和排序。