Scala 如何与一个未来合作,而这个未来又是一个什么样的未来?
在我当前的项目中,我使用了Scala 如何与一个未来合作,而这个未来又是一个什么样的未来?,scala,functional-programming,future,either,Scala,Functional Programming,Future,Either,在我当前的项目中,我使用了或[Result,HandbookModule](Result是一个HTTP状态码)作为返回类型,以便在出现问题时创建正确的状态。我现在已经将我的数据库访问重构为非阻塞的 此更改要求将数据库访问函数的返回类型更改为Future[Result,HandbookModule] 现在我不知道如何将这个函数与另一个返回或[Result,Long]的函数粘合在一起 为了更好地说明我的意思: def moduleDao.getHandbook(偏移量,限制):未来[结果,列表[模块
或[Result,HandbookModule]
(Result
是一个HTTP状态码)作为返回类型,以便在出现问题时创建正确的状态。我现在已经将我的数据库访问重构为非阻塞的
此更改要求将数据库访问函数的返回类型更改为Future[Result,HandbookModule]
现在我不知道如何将这个函数与另一个返回或[Result,Long]
的函数粘合在一起
为了更好地说明我的意思:
def moduleDao.getHandbook(偏移量,限制):未来[结果,列表[模块]]=未来(右(列表(模块(1)))
def NEXTOFSET(偏移量、限制、结果):要么[_,长]=右(1)
def GetHandbook(
抵销:长,
限制:长):未来[任一[结果,(列表[手册模块],长)]={
为了{
结果为了从将来打开方法,您必须阻止它并等待结果。您可以使用wait.result
但是阻止未来通常不是最好的做法。更多关于这一点
所以你们应该以不同的方式来解决这个问题。你们所面临的实际上是嵌套的monad堆栈的常见问题,它可以用monad转换器来处理
Scala的函数编程库提供了monad transformer的实现
在您的情况下,您可以使用EitherT.apply
将Future[orth[Result,List[Module]]
转换为EitherT[Future,Result,List[Module]]
和EitherT.fromOrth
来提升orth[\uu,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
}
导入cats.data.EitherT
进口猫_
def GetHandbook(
抵销:长,
限制:长
):Future[任一[String,(列表[String],Long)]={
val结果:EitherT[Future,String,(List[String],Long)]=for{
结果我不得不对发布的代码进行一些假设和调整/更正,以使其可用。(对于那些想帮助你的人来说,你不会让它变得容易。)
如果可以容忍默认的Long
值,则当nextofset()
返回Left
而不是Right[Long]
时,将显示为键入check和compile
def getHandbooks(offset: Long
,limit : Long
): Future[Either[Result, (List[Module], Long)]] =
moduleDao.getHandbooks(offset,limit).map(_.map(ms =>
(ms, nextOffset(offset,limit,ms).getOrElse(0L))))
如果我理解正确,您的左侧表示错误状态,对吗
如果是这样,我认为您应该重构API,使其既不使用也不使用,只需使用失败的Future
来表示错误状态
// Custom exception that wraps existing Result
case class MyCustomException(result: Result) extends Exception
class ModuleDao {
...
def getHandbooks(offset, limit): Future[List[Module] = {
// You'd probably want to do this asynchronously
// But for demonstration purposes
val origRetVal: Either[Result, List[Module] = ??? // current code returning your Either
origRetVal match {
case Right(modules: List[Module]) =>
Future.successful(modules)
case Left(result: Result) =>
// Failed future wrapping custom exception
Future.failed(MyCustomException(result))
}
}
...
}
为什么您需要更改它?为什么不只是在案例上,它对未来的计算是有效的?在我提供的示例中,这将起作用,但我也有一些更复杂的案例。尝试创建一个复杂的案例,这样会更容易帮助您。好的,我添加了一个更复杂的示例。希望它有用您的示例不会编译。