Scala 从Future[列表[A]]中获取头部未来的首选方法

Scala 从Future[列表[A]]中获取头部未来的首选方法,scala,future,Scala,Future,所以。。。假设我有一个Future[List[a]],我想要得到的是一个Future,它包含Future所包含的列表的第一个元素 考虑到这是db访问层的一部分,首选的方法是什么 def getFirstByName( name: String ): Future[ A ] = { val aListFuture = ... // somehow got the future of list of all A's for this name // Now how do I retur

所以。。。假设我有一个
Future[List[a]]
,我想要得到的是一个
Future
,它包含
Future
所包含的
列表的
第一个元素

考虑到这是db访问层的一部分,首选的方法是什么

def getFirstByName( name: String ): Future[ A ] = {
  val aListFuture = ...
  // somehow got the future of list of all A's for this name 
  // Now how do I return a Future[ A ] contaning the head of said list
}
这个问题的重点更多地放在
上,考虑到这是db访问层的一部分,最好的方法是什么?

我们可以像下面这样做
val aFuture=aListFuture.map(l=>l.head)
但是如果列表是空的呢

在这个问题上,我真正想要的是“如何设计一个可预测的解决方案?”

除了以特定于域的异常正常失败之外,还有其他选择吗?如果不是,我如何实施这种失败

我目前正在使用以下肮脏的伎俩

def getFirstByName( name: String ): Future[ A ] = {
  // somehow got the future of list of all A's for this name
  val aListFuture = ...
  aListFuture map( _.head ) match {
    case Some( t: Try[ A ] ) => t match {
      case Success( a: A ) => Promise.successful( a ).future
      case Failure( e: NoSuchElementException ) => Promise.failed( DbNotFound ).future
      case Failure( e ) => Promise.failed( e ).future
    }
    case _ => Promise.failed( new Exception( "Some unexplained exception" ) ).future
  }
}
试试这个:

val futureOfHead = aListFuture.map (_.head)
对于future返回空列表的情况,您可以提供默认值:

val DefaultValue = ...
val futureOfHead = aListFuture.map (_.headOption.getOrElse(DefaultValue))
另一种选择:

val futureOfHead = aListFuture.map (_.headOption.getOrElse(throw new RuntimeException("db layer exception"))

您可以使用
map
,然后使用
head

def map[S](f: (T) ⇒ S)(implicit executor: ExecutionContext): Future[S]
通过将函数应用于未来的成功结果,创建新的未来。如果此未来完成时存在异常,则新未来也将包含此异常

此dao的调用方可以处理
成功
失败

future.onComplete( {
  case Success(result) => ..
  case Failure(err) => .. //if head is empty you'll get java.util.NoSuchElementException
}

所有ANWSER都是正确的,但如果适合您的问题,可能会有一个不太容易出错的解决方案:

val aListFuture = futureList.map(l => l.headOption)
它返回一个可通过模式匹配检查的未来[Option[a]]

此外,如果您需要并具有此项的默认值,则可以使用:

val aListFuture = futureList.map(l => l.headOption.getOrElse(""))

为什么不改变函数返回类型?@FatihDonmez-Well。。。这违背了问题本身的全部要点。我需要这样做。如果列表是空的,也要考虑怎么做。但这不是很难以预料吗。如果列表是空的呢
l.head
在空列表中
l
不能说是非常明智的,对吗?您将如何从中恢复?如果假定的调用方已经有一个需要未来[a]
的合同怎么办?那么您应该使用headOption.getOrElse并在应用程序上下文中决定您的默认情况。那么。。。感谢您的输入,但在这里我真的在为这样的用例寻找Scala设计模式。虽然我不是Scala的高级专家,但我对Scala非常了解,除了使用
选项
,我至少可以用10种方法解决这个问题。。。我只是在寻找一个推荐的、优雅的解决方案。我们都在努力理解和帮助。至少有三个答案取决于相同的模式,所以也许最好先分享10种你认为它们不可靠、不有效等原因的其他思考方式。这样,我相信你可以找到更好的答案,为我们所有人拓宽知识面。没错。。。但这不是很难以预料吗。如果列表是空的呢?l、 一张空名单上的头我不能说很聪明,对吗?你将如何从中恢复?是的,但如何处理这种情况取决于你。一个选择是提供默认值。。。问题更多的是关于
考虑到这是db访问层的一部分,什么是做这件事的首选方式?
而不是关于如何获得不可预测的未来。如果这是db层的一部分,您认为
defaultValue
可以是什么?最好将其保留为headOption。不确定这种方法不“健壮”的地方在于,它是正确的、类型安全的方法,用于表示列表开头的值。
val aListFuture = futureList.map(l => l.headOption.getOrElse(""))