我很好奇递归构建Akka期货链的最佳方式,它将按顺序运行,如果未来的< code>doWork调用失败,未来将重试3次,如果重试次数用完,链将失败。假设所有< code>doWork调用都通过,则返回的futChain应该只完成。
object Main extends App {
val futChain = recurse(2)
def recurse(param: Int, retries: Int = 3): Future[String] {
Future {
doWorkThatMayFailReturningString(param...)
} recoverWith {
case e =>
if (retries > 0) recurse(param, retries -1)
else Future.failed(e)
} flatMap {
strRes => recurse(nextParam) //how should the res from the previous fut be passed?
}
}
futChain onComplete {
case res => println(res) //should print all the strings
}
}
您可以像这样实现可重试的Future
:
def retry[T](f: => Future[T])(n: Int)(implicit e: ExecutionContext): Future[T] = {
n match {
case i if (i > 1) => f.recoverWith{ case t: Throwable => retry(f)(n - 1)}
case _ => f
}
}
这没有针对尾部html" target="_blank">递归进行优化,但是如果您只打算重试几次,则不会得到堆栈溢出(我想如果它在前几个失败,无论如何它都会继续失败)。
然后我会单独做链接。如果您有有限数量的函数要链接在一起,每个函数都依赖于前面的函数(出于某种原因,您希望聚合结果),您可以使用< code > for comprehensions(< code > flat map 的语法糖):
for {
firstResult <- retry(Future(doWork(param)))(3)
secondResult <- retry(Future(doWork(firstResult)))(3)
thirdResult <- retry(Future(doWork(secondResult)))(3)
} yield List(firstResult, secondResult, thirdResult)
对于任意长的链,您可以使用 Future.sequence
(Akka 库中的 Futures
)并行执行它们:
def doWork(param: String): String = ...
val parameters: List[String] = List(...)
val results: Future[List[String]] = Future.sequence(parameters.map(doWork(_)))
这将解开本来是< code > List[Future[String]]到< code > Future[List[String]]的关系。
以下是按顺序执行类似操作的一种方法:
def sequential[A, B](seq: List[A])(f: A => Future[B])(implicit e: ExecutionContext): Future[List[B]] = {
seq.foldLeft(Future.successful(List[B]())) { case (left, next) =>
left.flatMap(list => f(next).map(_ :: list))
}
}
def doWork(param: String): String = ...
val results: Future[List[String]] = sequential(parameters)(param => Future(doWork(param)))
这些功能的实现对您的用例非常敏感。如果链中的任何期货失败,上述两个函数将返回失败的期货。有时候你会想要这个,有时候不会。如果您想只收集成功的期货,并放弃失败的期货而不放弃整个结果,您可以添加一个额外的步骤来恢复失败。
此外,recover
和 recoverWith 之间的
区别在于它接受的 PartialFunction
的类型。recover
将失败的 future 替换为默认值,而 recoverWith
使用另一个 Future 执行此操作
。在我重试
的情况下,recoverWith
更合适,因为我正在尝试用自身来恢复失败的未来
。
好吧,我想问题已经在标题中完成了。没什么大不了的,但我只是想知道。我有一个返回正确值或错误代码枚举项的方法。例如这样的东西: 其中返回一个Future,而只是修改数据。 现在我已经直观地编写了< code>Future[_],因为返回值是灵活的。但是在查看其他库时,我看到了< code>Future[Any]的用法。当你在函数的返回中使用匹配用例来检查它是什么数据时,这似乎也是合乎逻辑的。 例如,
任务是实现递归方法,返回 Future 并且由于这一部分("在其他递归(结果::: res,尝试1)")代码失败与错误,因为它期望未来[Seq[结果]],但实际上返回未来[对象]。 据我所知,问题在于yield块内的表达式必须返回Seq[Result],以便将来由Monad进行后续包装。但是“递归(结果::res,尝试1)”将返回未来。因此,不是预期的Seq[Result]收益率,而是包含未来的[
我在写一个小服务器。一篇博文特别推荐了这种提问模式。课程具有以下特点: 我正在检索这个数据库行,如果它不存在或发生了一些错误,我想从Spray发送一个响应来告诉客户端。 然而,使用这种模式,我不知道在哪里注入开关。 我试着把代码改成这样: Spray使用发送HTTP响应可以接受两个对象,也可以接受一个字符串/可序列化对象。我想使用双对象模式(它允许我手动编码它的标题),理想的情况应该是 有没有办法
left join 和 inner join的区别 线程池的调用顺序 Spring循环依赖和三级缓存 AOP机制 索引 最左前缀原则的失效 ABCD 有>号 范围查询后会失效 MVCC的实现 可不可以实习
JavaScript未来的模块化会是什么样子?这很难讲。如前所说,ES6已经开始起草这一块的标准,而AMD,CommonJS已经流行起来。通常,标准的制定,都是在有了实现的前提之下。不管怎样,我们先来展望一二吧。
问题内容: 信封:Akka 2.1,scala版本2.10.M6,JDK 1.7,u5 现在是我的问题:我有: 现在在第一行中,我有一个Future对象的Future,有什么方法可以在不阻塞当前线程的情况下将其转换为Future? Akka有什么方法吗?据我检查,我还没有发现…第一次发帖....不好意思的格式和组织…:〜P 问题答案: 简短答案(英语):flatMap dat sh!t 较短的答案