如何验证Future [List [T]]中的单个元素以返回Future [List [T]]或抛出异常

问题描述 投票:0回答:1

这里不需要关注函数的用途,它仅用于演示:

def readAllByPersonOrFail(person: Person, otherPersonId: Long): Future[List[Person]] = {
  val personSiblingsFuture: Future[List[Person]] = personSiblingsDomain.readAllByPersonId(person.id)
  personSiblingsFuture.map { persons =>
    persons.find(_.id == otherPersonId) match {
      case Some(person) =>
        person.isActive match {
          case true => person
          case false => throw new IllegalArgumentException("something inactive")
        }
      case None => throw new IllegalArgumentException("something wrong ehre")
    }
  }
  personSiblingsFuture
}

我想返回personSiblingsFuture上面iff它验证(确保正确的人在列表中并且是活动的),否则抛出异常。我认为上面的代码没有做正确的事情,因为它在失败时不存在。

scala functional-programming
1个回答
0
投票

看看scala.concurrent.Future.map。这创造了一个新的未来,通过将函数应用于此未来的成功结果来解决其价值。

请注意,在这里,您将丢弃刚刚使用.map()创建的未来。

有几个方面可以解决您的问题,但您应该更深入地质疑使用Futures的异常。 Scala专门提供FutureOptionTry等概念,以避免抛出异常并拥有更清晰的控制流。

选项1,返回映射的未来

在你的功能中,

def func(...): Future[List[Person]] {
  val personSiblingsFuture = ...;
  personSiblingsFuture.map { persons =>
    ...
  }
}
// note we're not returning personSiblingsFuture,
// but the mapped result

当有人真正试图获得未来的价值时,例如通过使用.value,他们可能会看到异常intead:

def main() {
  val future = func(...);  // this is fine
  val my_list = future.value;  // awaits Future, might throw here
}

选项2,实际上等待列表并抛出函数

返回一个可能抛出的未来很奇怪,如果你实际明确地拥有一个可能抛出的函数,那么可能会更容易一些,例如

/** jsdoc describing function **/
def funcMightThrow(...): List[Person] {
  val personSiblingsFuture = ...;
  val personSiblings = personSiblingsFuture.value;

  personSiblings.find(_.id == otherPersonId) match {
    case Some(person) =>
      person.isActive match {
        case true => personSiblings
        case false => throw new IllegalArgumentException("something inactive")
      }
    case None => throw new IllegalArgumentException("something wrong ehre")
  }
}

选项3,考虑使返回类型更明确

def func(...): Future[Try[List[Person]]] {
  val personSiblingsFuture = ...;
  personSiblingsFuture.map { persons =>
    ...
    // successful case returns 'persons' (List[Person])
    // fail cases return Failure(...) instead
  }
}  // return the mapped future

你也可以使用Try[List[Person]]返回Future[]而不是.value,这使得func成为阻挡函数。

© www.soinside.com 2019 - 2024. All rights reserved.