Scala Фьючерсы возвращают пустой список после ожидания - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть программа, которая выполняет:

Await.result(Processor.validateEntries(queuedEntries)), Duration.Inf)

И метод validateEntries вызывает другой метод, который выполняет:

val validatedEntries: ListBuffer[Entries] = new ListBuffer[Entries]

for (entry <- queuedEntries) {
checkEntry(entry.name).map(.......... validatedEntries += Entries(...) )
}
Future(validatedEntries.toList)

, где checkEntry возвращает Future[Boolean].

def checkEntry(name: String): Future[Boolean] = {
    checkNameAlreadyExists(name).flatMap(exists =>
        buildRequest(exists, name).map(response => {
            if (!response.contains("error")) {
                true
            } else {
                false
            }
        })
    )
}

На верхнем уровне, где я выполняю Await.result, я также получаю пустой список: List(). Любые предложения очень помогут!

Ответы [ 2 ]

4 голосов
/ 28 февраля 2020

Смешивание изменяемых коллекций и параллелизма - не хорошая идея. Рассмотрим рефакторинг checkEntry для возврата, скажем, Future[Option[Entry]] вместо Future[Boolean], где Some будет означать успешную проверку, в то время как None неуспешно, и тогда вы можете сделать что-то вроде

case class Entry(v: Int)
val queuedEntries = List(Entry(1), Entry(2), Entry(3))
def checkEntry(entry: Entry): Future[Option[Entry]] = ???

Future
  .traverse(queuedEntries)(checkEntry)
  .map(_.flatten)

Если оставить checkEntry как есть, вы можете попробовать что-то вроде

case class Entry(v: Int)
val queuedEntries = List(Entry(1), Entry(2), Entry(3))
def checkEntry(entry: Entry): Future[Boolean] = Future(Random.nextBoolean)

Future
  .traverse(queuedEntries)(checkEntry)
  .map(checkedEntries => checkedEntries zip queuedEntries)
  .map(_.collect { case (validated, entry) if validated => entry} )
0 голосов
/ 28 февраля 2020

Вы должны использовать для понимания. Сначала вы должны прочитать список, а в yield, вы должны вызвать функцию один за другим и ждать завершения в будущем с помощью yield

package com.vimit.StackOverflow

import scala.concurrent._
import ExecutionContext.Implicits.global


object FutureProblem extends App {


  val list = List(1, 2, 3)
  val outputList = List()

  val result = for {
    value <- list
  } yield {
    for {
      result <- getValue(value).map(res => outputList ++ List(value))
    } yield result
  }

  print(result)

  def getValue(value: Int) = Future(value)

}
.
...