我有一份事情清单,让我们说一下字符串 我想把它变成一个Future [List []]的东西,让我们再说一下Strings 并行执行不需要。
这将以Action.async结束,因此不欢迎阻止。
我有一个可以在将来转换元素的处理程序 简化为:
def handle( input: String ): Future[ String ] =
{
input match {
case "X" => Future.failed( new Exception( "failed on "+input ) )
case other => Future.successful( "handled "+other )
}
}
最后,我想返回一个Future [List [...]],包括第一个失败的结果,然后停止 可以简化为:
def handleInOrder( inputs: List[ String ] ): Future[ List[ String ] ] = {
val output = new ListBuffer[ String ]( )
breakable { for( input <- inputs ){
Await.ready( handle( input ), Duration.Inf ).value.get match {
case Success( result ) => output += result;
case Failure( reason ) => output += "Ex:"+reason; break
}
} }
Future.successful( output.toList )
}
处理事情的顺序很重要。
这样可以正常工作,但我真的想摆脱这种情况&#34; Await.ready &#34;。
我希望我的问题很清楚,目前我无法解决这个问题。
致电
handleInOrder( List( "a", "b", "X", "c" )
应该返回
List(handled a, handled b, Ex:java.lang.Exception: failed on X)
答案 0 :(得分:0)
您可以使用foldLeft
按顺序执行Future
。
def handleInOrder(inputs: List[String]): Future[List[String]] = {
inputs.foldLeft(Future.successful(ListBuffer.empty[String])) { case (acc, next) =>
handle(next).recover { case t: Throwable => "Ex: " + t.getMessage}
.flatMap(f => acc.map(_ += f))
}.map(_.toList)
}
这将recover
Future
handle
来自Future[List[String]]
,并将其替换为包含异常消息的成功消息。如果您希望整个recover
在一个错误输入上失败,则可以从链中删除{{1}}。
答案 1 :(得分:0)
我建议使用Either
(或scalaz \/
)来处理您的成功或失败,并为意外失败保留Future.failure
,就像很多人建议的那样不要对“正常”控制流使用例外。然后,您的返回值可以是合理的类型,而不是随机包含List
和String
的{{1}}。
Throwable
答案 2 :(得分:0)
这将在第一次失败时停止:
def handleInOrder(inputs: List[String]): Future[List[String]] = {
def run(inputs: List[String], output: ListBuffer[String]): Future[ListBuffer[String]] = inputs match {
case h :: t => handle(h).flatMap{x => run(t, output += x)}.recover{ case t: Throwable => output += ("Ex: " + t.getMessage)}
case _ => Future { output }
}
run(inputs, ListBuffer.empty[String]).map(_.toList)
}