而Scala中的期货循环
我有两种方法:而Scala中的期货循环,scala,future,Scala,Future,我有两种方法: def getNextJob:Future[选项[Job]] def过程(作业:作业):未来[单位] 我希望处理所有作业,直到没有剩余作业 我可以用waite.g private def process()(implicit ctx: ExecutionContext): Future[Unit] = { var job: Option[Job] = Await.result(service.getNextJob, FiniteDuration(2, TimeUnit.S
def getNextJob:Future[选项[Job]]
def过程(作业:作业):未来[单位]
我希望处理所有作业,直到没有剩余作业
我可以用wait
e.g
private def process()(implicit ctx: ExecutionContext): Future[Unit] = {
var job: Option[Job] = Await.result(service.getNextJob, FiniteDuration(2, TimeUnit.SECONDS))
while(job.isDefined) {
Await.result(process(job.get), FiniteDuration(2, TimeUnit.SECONDS))
job = Await.result(service.getNextJob, FiniteDuration(2, TimeUnit.SECONDS))
}
Future.successful()
}
但这是丑陋的,不能正确使用期货。有没有一种方法可以让我用某种方式来取代这个
def go()(implicit ctx: ExecutionContext): Future[Unit] =
getNextJob.flatMap { maybeJob ⇒
if(maybeJob.isDefined) process(maybeJob.get).flatMap(_ ⇒ go())
else Future.unit
}
注意:它不是尾部递归
def processAll()(implicit ec: ExecutionContext): Future[Unit] =
getNextJob.flatMap {
case Some(job) => process(job).flatMap(_ => processAll())
case None => Future.unit
}
注意:它不是尾部递归
def processAll()(implicit ec: ExecutionContext): Future[Unit] =
getNextJob.flatMap {
case Some(job) => process(job).flatMap(_ => processAll())
case None => Future.unit
}
要同时处理它们,请执行以下操作:
def processAll()(implicit ec: ExecutionContext): Future[Unit] =
getNextJob.flatMap {
case Some(job) => process(job).zipWith(processAll())((_,_) => ())
case None => Future.unit
}
要同时处理它们,请执行以下操作:
def processAll()(implicit ec: ExecutionContext): Future[Unit] =
getNextJob.flatMap {
case Some(job) => process(job).zipWith(processAll())((_,_) => ())
case None => Future.unit
}
你想像示例代码那样严格地处理作业,还是可以按任何顺序执行作业?@Tim任何顺序都可以,我只需要确保一次运行1我想我不明白为什么
process
会返回一个Future
,如果你总是在继续下一个作业之前等待它完成。如果不等待它完成,则可以同时处理多个作业。@Tim我不打算进入实现,但getNextJob
只是从数据库中提取一个状态为未处理的作业<代码>处理
处理它并将状态更新为完成
。如果我并行处理多个,则无法保证(使用我当前的实现)当两次调用getNextJob
时,该作业只运行一次,可能会两次返回同一作业`在这种情况下,您可能应该避免从process
返回Future
,只需让它执行处理,然后返回Unit
。这已经从getNextJob
运行在Future
中,因此不需要在第一个Future
中嵌套另一个Future
。您希望按照示例代码中的严格顺序处理作业,还是可以按任意顺序执行它们?@Tim任意顺序都可以,我只需要确保一次运行1我想我不明白为什么进程
会返回一个未来
,如果您总是等待它完成,然后再进行下一个作业。如果不等待它完成,则可以同时处理多个作业。@Tim我不打算进入实现,但getNextJob
只是从数据库中提取一个状态为未处理的作业<代码>处理
处理它并将状态更新为完成
。如果我并行处理多个,则无法保证(使用我当前的实现)当两次调用getNextJob
时,该作业只运行一次,可能会两次返回同一作业`在这种情况下,您可能应该避免从process
返回Future
,只需让它执行处理,然后返回Unit
。这已经在getNextJob
的Future
中运行,因此不需要在第一个Future
中嵌套另一个Future
。它实际上根本不是递归的:)注意,选项.get
是“代码气味”,应该避免。您应该使用类似于case-Some(job)=>process(job.flatMap(=>go());case None=>Future.unit
instead赞同@Dima对这个答案的建议,非常感谢!注意,由于这是一个未来的函数,所以不是尾部递归的函数不应该是一个问题,它实际上根本不是递归的:)注意,Option.get
是“代码气味”,应该避免使用。您应该使用类似于case-Some(job)=>process(job.flatMap(=>go());case None=>Future.unit
instead赞同@Dima对这个答案的建议,非常感谢!注意,由于这是未来的事情,所以函数不是尾部递归的应该不会有问题,这将一次处理一个作业,对吗?如果是,如何修改它以同时处理作业?@CervEd补充道。不过警告一下,我是凭记忆写的,所以它可能不适合你!我使用了类似于Future.sequence{(1到X).map(processAll(…)}
,其中X是我希望一次处理的请求数,但感觉不正确这将一次处理一个作业,对吗?如果是,如何修改它以同时处理作业?@CervEd补充道。不过警告一下,我是凭记忆写的,所以它可能不适合你!我使用了类似于Future.sequence{(1到X).map(processAll(…)}
,其中X是我希望一次处理的请求数,但感觉不正确