Scala: последовательное будущее

Я хочу последовательно обрабатывать это вложенное будущее для каждого элемента, который я передаю с помощью итератора.

Я связал фьючерсы с помощью flatMap и Map, правильно ли это?

Что мне нужно сделать, чтобы выполнить процесс желаемым образом (показано ниже) с использованием какого-либо инструмента блокировки и без него?

object Main{

Iterator.foreach{e=>
process(e)
 }
}


object A {

def doOne(e): Future[Any] = Future {
println("startFirst");      Thread.sleep(3000);     
 }

def doTwo(Any): Future[Any] = Future {
println("startSecond");      Thread.sleep(1000);      
}


 def doThree(Any): Future[Any] = Future {
println("do 3");     Thread.sleep(1000);     
}

  def doFour(e,Any): Future[Unit] = Future {
println(s"do 4&processComplete$e");     Thread.sleep(1000);     
  }

def process(e):Future[Unit]={

val a= doOne(e)
.flatMAp{a=> doTwo(a)}
.flatMap{b=>doThree(b)}
.map{c=> doFour(c)}

 }

Если я передам 3 элемента (e1,e2,e3) в процесс определения, я ожидаю, что программа напечатает:

    startFirst (e1)
    startSecond(e1)
    startThree (e1)
    startFour&processComplete  (e1)
    startFirst (e2)
    startSecond(e2)
    startThree (e2)
    startFour&processComplete  (e2)
    startFirst (e3)
    startSecond(e3)
    startThree (e3)
    startFour&processComplete  (e3)

Вместо:

    startFirst (e1)
    startFirst (e2)
    startFirst (e3)
    startSecond(e1)
    startSecond(e2)
    startSecond(e3)
    startThree (e1)
    startThree (e2)
    startThree (e3)
    startFour&processComplete  (e1)
    startFour&processComplete  (e2)
    startFour&processComplete  (e3)

person Andrew Granata    schedule 26.06.2020    source источник


Ответы (1)


Вы можете сделать что-то вроде этого:

def sequentialTraverse_[A](col: IterableOnce[A])(f: A => Future[Any])(implicit ec: ExecutionContext): Future[Unit] =
  col.iterator.foldLeft(Future.successful(())) {
    case (accF, a) =>
      accF.flatMap(_ => f(a)).map(_ => ())
  }

Который вы также можете преобразовать в метод расширения, чтобы вы могли сделать что-то вроде:

List("A", "B", "C").sequentialTraverse_(process)

Вы можете увидеть, как это работает здесь.

person Luis Miguel Mejía Suárez    schedule 26.06.2020
comment
Чтобы добавить деталь для читателей, которым это может быть интересно: подчеркивание в конце имени метода является установленным соглашением об именах (знакомым, в частности, разработчикам Haskell), что обычно означает, что мы не заинтересованы в возвращаемом значении здесь, эта функция должен быть интересен своими эффектами. - person stefanobaghino; 27.06.2020