Scala 当onSuccess和onFailure是def中的最后一条语句时,它们不会返回任何内容

Scala 当onSuccess和onFailure是def中的最后一条语句时,它们不会返回任何内容,scala,scala-collections,scalaz,Scala,Scala Collections,Scalaz,我正在尝试收集期货,但在根据未来状态从def返回结果时遇到困难。下面是我的代码: final case class StagesToRun(stages : Set[StageRun]) private def processNextStagesAndAccumulateResults(stagesToRun: StagesToRun): \/[Exception, Success] = { val stageProcessingExceptions = mutable.Set[Exceptio

我正在尝试收集期货,但在根据未来状态从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约定,函数的最后一条语句将成为函数的返回语句。在此函数中,它基本上应该是if stageProcessingExceptions.isEmpty Success及其相应的else的输出,或者是onFailure的结果,即new Exceptionex.getMessage。然而,编译器一直告诉我返回类型是unit而不是预期的析取。有人能帮我吗?谢谢

您说函数的最后一条语句变成了return语句,这是完全正确的。但是,如果您看到onSuccess和onFailure的方法定义,则它们都将Unit作为返回类型返回

从scala文档中,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()
        }
onSuccess和onFailure返回单元和都是为实现副作用而设计的。如果要返回已修改的未来,请使用“转换”。其中一个版本包含两个功能:第一个功能处理成功的结果,第二个处理异常

processResults.transform(
  { result =>
    // process result and return new result
    // throw error on failure
    result
  },
  { ex =>
    // Process exception and return new exception
    ex
  }
)
如果在任何一个函数中抛出异常,将来都会出现错误


还有另一个版本的transform,它使用函数Try=>Try,允许您将错误的未来转化为成功的未来,这在上述版本中是不可能的。

onSuccess和onFailure不是为返回而设计的。它们的设计目的是在不阻塞其余代码的情况下捕获结果。感谢@Tim的回复,我尝试了转换和映射。现在我知道了这两种方法的原理:谢谢你的回复。这张地图和我预想的一样完美。