在 Scala 函数中处理副作用和 return 值的惯用方法
Idiomatic way to handle side effect and return value in Scala functions
您将如何构建一个既要产生副作用又要 return 值的函数?
例如我想要以下功能:
def futureFromHttpCall: Future[HttpResponse] =
doHttpCall.foreach(publishDomainEvent).returnOriginalFuture
(不知怎的,我有一种感觉,monads 会出现,所以如果这是我对猫有点熟悉的路径,如果那里有解决这个问题的方法?)
我能想到的最简单的事情是 "hiding" 返回方法中的副作用而不是 Future[T]
,将其公开为未来的延续:
def futureFromHttpCall: Future[HttpResponse] = doHttpCall
然后你可以 onComplete
作为副作用:
futureFromHttpCall.onComplete {
case Success(_) => publishDomainEvent
case Failure(e) => // Stuff
}
使效果明确。或者,如果您在演员系统中,您可以 pipeTo
Future
到您的 receive
方法并在那里处理成功/失败。
我认为你的 Future 应该只有在你所有的域事件都被推送时才会完成。它们也应该是 Future
。然后就可以用Future.sequence
等待全部完成再返回。
你的问题有点不清楚,但我假设 doHttpCall 是某种类型的列表。
def doHttpCall(): Future[Seq[X]] = ???
def publishDomainEvent(x:X): Future[Unit] = ???
def futureFromHttpCall(): Future[Seq[X]] = {
val firstFuture = ???
firstFuture.flatMap { xs =>
val xxs: Seq[Future[Unit]]= xs.map(publishDomainEvent)
Future.sequence(xxs).map { _ => re }
}
}
所有这些等待在测试时都非常有用。
您将如何构建一个既要产生副作用又要 return 值的函数? 例如我想要以下功能:
def futureFromHttpCall: Future[HttpResponse] =
doHttpCall.foreach(publishDomainEvent).returnOriginalFuture
(不知怎的,我有一种感觉,monads 会出现,所以如果这是我对猫有点熟悉的路径,如果那里有解决这个问题的方法?)
我能想到的最简单的事情是 "hiding" 返回方法中的副作用而不是 Future[T]
,将其公开为未来的延续:
def futureFromHttpCall: Future[HttpResponse] = doHttpCall
然后你可以 onComplete
作为副作用:
futureFromHttpCall.onComplete {
case Success(_) => publishDomainEvent
case Failure(e) => // Stuff
}
使效果明确。或者,如果您在演员系统中,您可以 pipeTo
Future
到您的 receive
方法并在那里处理成功/失败。
我认为你的 Future 应该只有在你所有的域事件都被推送时才会完成。它们也应该是 Future
。然后就可以用Future.sequence
等待全部完成再返回。
你的问题有点不清楚,但我假设 doHttpCall 是某种类型的列表。
def doHttpCall(): Future[Seq[X]] = ???
def publishDomainEvent(x:X): Future[Unit] = ???
def futureFromHttpCall(): Future[Seq[X]] = {
val firstFuture = ???
firstFuture.flatMap { xs =>
val xxs: Seq[Future[Unit]]= xs.map(publishDomainEvent)
Future.sequence(xxs).map { _ => re }
}
}
所有这些等待在测试时都非常有用。