尽管失败,如何继续执行Future序列? [英] How to carry on executing Future sequence despite failure?

查看:14
本文介绍了尽管失败,如何继续执行Future序列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自 Future 对象的 traverse 方法在第一次失败时停止.我想要这个方法的一个宽容/宽容的版本,它在发生错误时继续执行序列的其余部分.

The traverse method from Future object stops at first failure. I want a tolerant/forgiving version of this method which on occurrence of errors carries on with the rest of the sequence.

目前我们已将以下方法添加到我们的工具中:

Currently we have added the following method to our utils:

def traverseFilteringErrors[A, B <: AnyRef]
                           (seq: Seq[A])
                           (f: A => Future[B]): Future[Seq[B]] = {
  val sentinelValue = null.asInstanceOf[B]
  val allResults = Future.traverse(seq) { x =>
    f(x) recover { case _ => sentinelValue }
  }
  val successfulResults = allResults map { result =>
    result.filterNot(_ == sentinelValue)
  }
  successfulResults
}

有没有更好的方法来做到这一点?

Is there a better way to do this?

推荐答案

真正有用的事情(一般来说)是能够将未来的错误转化为正确的价值.或者换句话说,将一个 Future[T] 转换成一个 Future[Try[T]](成功的返回值变成了一个 Success[T]code> 而失败案例变成了 Failure[T]).下面是我们如何实现它:

A genuinely useful thing (generally speaking) would be to be able to promote the error of a future into a proper value. Or in other words, transform a Future[T] into a Future[Try[T]] (the succesful return value becomes a Success[T] while the failure case becomes a Failure[T]). Here is how we might implement it:

// Can also be done more concisely (but less efficiently) as:
// f.map(Success(_)).recover{ case t: Throwable => Failure( t ) }
// NOTE: you might also want to move this into an enrichment class
def mapValue[T]( f: Future[T] ): Future[Try[T]] = {
  val prom = Promise[Try[T]]()
  f onComplete prom.success
  prom.future
}

现在,如果您执行以下操作:

Now, if you do the following:

Future.traverse(seq)( f andThen mapValue )

您将获得一个成功的 Future[Seq[Try[A]]],其最终值包含每个成功未来的 Success 实例,以及一个 Failure 每个失败的未来实例.如果需要,您可以在此序列上使用 collect 删除 Failure 实例并仅保留成功的值.

You'll obtain a succesful Future[Seq[Try[A]]], whose eventual value contains a Success instance for each successful future, and a Failure instance for each failed future. If needed, you can then use collect on this seq to drop the Failure instances and keep only the sucessful values.

换句话说,您可以按如下方式重写您的辅助方法:

In other words, you can rewrite your helper method as follows:

def traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B]): Future[Seq[B]] = {
  Future.traverse( seq )( f andThen mapValue ) map ( _ collect{ case Success( x ) => x } )
}

这篇关于尽管失败,如何继续执行Future序列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆