而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是我希望一次处理的请求数,但感觉不正确