Scala:*.map(*) 运行 在 Future 中,如何中止地图?
Scala: *.map(*) running in a Future, how to abort map?
@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
的解决方案。
对于快速解决方案,您可以将 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)}
如果不需要这个结果,可以再创建一个future,这个future会在你的breakRequested
改变后完成。并使用方法 Future.firstCompletedOf
.
@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
的解决方案。
对于快速解决方案,您可以将 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)}
如果不需要这个结果,可以再创建一个future,这个future会在你的breakRequested
改变后完成。并使用方法 Future.firstCompletedOf
.