onSuccess和onFailure在def中的最后一个语句时不返回任何内容

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

我正在努力处理期货的收集,并且无法根据未来状态从def返回结果。以下是我的代码:

final case class StagesToRun(stages : Set[StageRun])
private def processNextStagesAndAccumulateResults(stagesToRun: StagesToRun): \/[Exception, Success] = {
val stageProcessingExceptions = mutable.Set[Exception]()
//processor.process(stagesToRun) => returns a Set[Future[\/[Exception, Success]]] and I am converting it to  Future[Set[\/[Exception, Success]]] in below expression
val processResults = Future.sequence(processor.process(stagesToRun))
processResults.onSuccess {
  case result => {
    result.map { res =>
      res.fold(
        l => stageProcessingExceptions += l,
        r => r
      )
    }
    if (stageProcessingExceptions.isEmpty) Success.right
    else new Exception("Got exception while processing one of the stage").left
  }
}
processResults.onFailure {
  case ex =>  new Exception(ex.getMessage)).left
}
}

现在按照Scala约定,我的函数的最后一个语句成为我函数的return语句。在这个函数中,它应该基本上是if (stageProcessingExceptions.isEmpty) Success及其相应的else的输出或onFailure的结果,即new Exception(ex.getMessage))。然而,编译器继续告诉我返回类型是单位而不是预期的分离。有人可以帮我吗?谢谢

scala scala-collections scalaz
2个回答
5
投票

当你说函数的最后一个语句成为return语句时,你是完全正确的。但是,如果您看到onSuccessonFailure的方法定义,则它们都返回Unit作为返回类型。

从scala docs,onSuccess的签名是

def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = onComplete {
    case Success(v) =>
      pf.applyOrElse[T, Any](v, Predef.identity[T]) // Exploiting the cached function to avoid MatchError
    case _ =>
  }

在类似的线上onFailure返回单位。

 def onFailure[U](@deprecatedName('callback) pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Unit = onComplete {
    case Failure(t) =>
      pf.applyOrElse[Throwable, Any](t, Predef.identity[Throwable]) // Exploiting the cached function to avoid MatchError
    case _ =>
  }

在您的情况下,您可以做的是对未来应用map函数而不是onComplete。这将帮助您传播所需的类型。此外,如果您想要处理未来失败的情况,可以将恢复块添加到您的未来

 .recover {
          case _ =>
         //whatever type you want to propogate ex: Left()
        }

3
投票

onSuccessonFailure都返回Unit,旨在实现副作用。如果你想返回修改后的Future,请使用transform。其中一个版本需要两个函数:第一个函数处理成功结果,第二个函数处理异常。

processResults.transform(
  { result =>
    // process result and return new result
    // throw error on failure
    result
  },
  { ex =>
    // Process exception and return new exception
    ex
  }
)

如果你在任一函数中抛出异常,你将得到一个错误Future

还有另一个版本的transform,它采用了一个函数Try => Try,它允许你将错误Future变成成功的Future,这是上述版本无法实现的。

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