Scala:* .map(*)在Future中运行,如何中止map?

时间:2016-06-16 18:53:47

标签: scala loops mapping future break

@volatile var breakRequested: Boolean = false
// ...
def futureFunc(): Option[Iterable[String]] = {
  val result = hugeList.map { item =>
    if(breakRequested) {
      // put exit code here
      // return None
      // throw AnException
      // what else?
    }
    item.toText() // time-expensive function
  }
  Some(result)
}
Future { futureFunc() }

鉴于有人将breakRequested标记设置为true:我如何退出map

我尝试了什么:

return None =>这样的return转换为scala.runtime.NonLocalReturnControl:我试图捕捉到这个错误,但它似乎无法捕获(绕过try / catch)。

object Cancelled extends Exception:我试图抛出这个,但也无法抓住它。

当我通过SBT运行应用程序时,所有异常都显示在命令行中。

如果可能的话,我更喜欢没有try / catch的解决方案。

1 个答案:

答案 0 :(得分:1)

对于快速解决方案,您可以将 hugeList 转换为Iterator,然后使用takeWhile

...
val result = hugeList.toIterator
  .takeWhile(_ => !breakRequested)
  .map { item => 
    item.text
  }
...

修改 Scala的Future没有取消,但是twitter Future已经取消了。要取消此使用方法raise

您也可以编写自己的map,例如:

@annotation.tailrec def map[T,R](
  src: List[T], 
  cancel: => Boolean, 
  dsc: List[R] = List.empty[R])(f: T => R):List[R] = src match {
    case _ if cancel => dsc
    case h :: t => map(t, cancel, f(h) :: dsc)(f)
    case Nil => dsc
}
Future{map(hugeList, breakRequested)(_.text)}

如果您不需要结果,则可以创建另一个未来,这将在breakRequested更改后完成。并使用方法Future.firstCompletedOf