作者:抵达不了了的叫幸福_999 | 来源:互联网 | 2023-06-06 14:24
在我当前的项目中,我使用Either[Result, HandbookModule]( Resultis an HTTP Statuscode) 作为返回类型,以便在出现问题时创建正确的状态。我现在已
在我当前的项目中,我使用Either[Result, HandbookModule]
( Result
is an HTTP Statuscode) 作为返回类型,以便在出现问题时创建正确的状态。我现在已经将我的数据库访问重构为非阻塞。
此更改要求我的数据库访问函数的返回类型更改为Future[Either[Result, HandbookModule]]
.
现在我不确定如何将此函数与另一个返回Either[Result, Long]
.
所以为了更好地说明我的意思:
def moduleDao.getHandbooks(offset, limit): Future[Either[Result, List[Module]] = Future(Right(List(Module(1))))
def nextOffset(offset, limit, results): Either[_, Long] = Right(1)
def getHandbooks(
offset: Long,
limit: Long): Future[Either[Result, (List[HandbookModule], Long)]] = {
for {
results <- moduleDao.getHandbooks(offset, limit)
offset <- nextOffset(offset, limit, results)
} yield (results, offset)
}
在更改之前,这显然没有问题,但我不知道最好的方法是什么。
或者有没有办法将 a 转换Future[Either[A, B]]
为 an Either[A, Future[B]]
?
回答
为了从 Future 中解开你的方法,你必须阻塞它并等待结果。你可以使用Await.result
.
但是阻止未来通常不被认为是最佳实践。更多关于这里。
所以你应该以不同的方式解决这个问题。您面临的实际上是嵌套 monad 堆栈的常见问题,并且可以使用 monad 转换器来处理。
Scala 的函数式编程库cats提供了一个EitherT monad 转换器的实现。
在您的情况下,您可以使用EitherT.apply
to 转换Future[Either[Result, List[Module]]
为EitherT[Future, Result, List[Module]]
和EitherT.fromEither
提升Either[_, Long]
.
它可能看起来像这样:
import cats.data.EitherT
import cats.implicits._
def getHandbooks(
offset: Long,
limit: Long
): Future[Either[String, (List[String], Long)]] = {
val result: EitherT[Future, String, (List[String], Long)] = for {
results <- EitherT(moduleDao.getHandbooks(offset, limit))
offset <- EitherT.fromEither[Future](nextOffset(offset, limit, results))
} yield (results, offset)
result.value //unwrap result from EitherT
}