Reputation: 9559
Let's say I have a function
def request(url: String): Future[String]
and need to write a function
def requestFirst(urls: List[String]): Future[String]
that calls request(url) in sequence untill it completes successfully (in this case the successful value is returned) or requests for all urls fail (in this case all failures are returned).
How can this be done in Scala?
Upvotes: 2
Views: 203
Reputation: 9559
This is what I came up with based on @parnav-shukla answer:
def requestFirst(urls: List[String]): Future[String] = {
def requestFirstInternal(urlSubset: List[String], errors: Seq[String]): Future[String] = {
if(urlSubset.isEmpty) {
Future.failed(new Exception(errors.mkString("\n")))
} else {
request(urlSubset.head) recoverWith { t =>
requestFirstInternal(urlSubset.tail, errors ++ Seq(t.getMessage))
}
}
}
requestFirstInternal(urls, Seq.empty)
}
Upvotes: 0
Reputation: 2226
def requestFirst(urls: List[String]): Future[String] = {
val default: Future[String] = Future.failed(new scala.Exception("all failed"))
urls.foldLeft(default)((prevFuture, currentUrl) => {
prevFuture fallbackTo (request(currentUrl))
})
}
OR
def requestFirst(urls: List[String]): Future[String] = {
def requestFirstInternal(urlSubset: List[String]): Future[String] = {
if(urlSubset.isEmpty) {
Future.failed(new Exception("Exhausted all urlSubset"))
} else {
request(urlSubset.head) fallbackTo {
requestFirstInternal(urlSubset.tail)
}
}
}
requestFirstInternal(urls)
}
Upvotes: 2