使用Scala futures列表和onComplete进行异步处理以进行异常处理

使用Scala futures列表和onComplete进行异步处理以进行异常处理,scala,asynchronous,concurrency,future,Scala,Asynchronous,Concurrency,Future,我试图进行大量的外部服务调用,每次调用后都会进行异常处理和有条件的进一步处理。我原以为在内部使用.onComplete扩展这个nice()示例会很容易,但似乎我对范围界定和/或未来不太了解。谁能给我指一下正确的方向吗 #!/bin/bash scala -feature $0 $@ exit !# import scala.concurrent.{future, blocking, Future, Await} import scala.concurrent.ExecutionContext.

我试图进行大量的外部服务调用,每次调用后都会进行异常处理和有条件的进一步处理。我原以为在内部使用.onComplete扩展这个nice()示例会很容易,但似乎我对范围界定和/或未来不太了解。谁能给我指一下正确的方向吗

#!/bin/bash
scala -feature $0 $@
exit
!#

import scala.concurrent.{future, blocking, Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.util.{Success, Failure}
import scala.language.postfixOps

val keylist = List("key1", "key2")

val myFuts: List[Future[String]] = keylist.map {
  myid => future {
    // this line simulates an external call which returns a future (retrieval from S3)
    val myfut = future { Thread.sleep(1); "START " + myid}

    var mystr = "This should have been overwritten"
    myfut.onComplete {
      case Failure(ex) => {
        println (s"failed with error: $ex")
        mystr = "FAILED"
      }
      case Success(myval) => {
        mystr = s"SUCCESS $myid: $myval"
        println (mystr)
      }
    }
    mystr
  }
}

val futset: Future[List[String]] = Future.sequence(myFuts)
println (Await.result(futset, 10 seconds))
在我的计算机(Scala 2.10.4)上,这会打印:

SUCCESS key2: START key2
SUCCESS key1: START key1
List(This should have been overwritten, This should have been overwritten)
我想要(订单不重要):


完成后不会返回一个新的未来,它只允许您在未来完成时做一些事情。因此,未来的第一个块将在执行onComplete之前返回,因此您将返回字符串的原始值

我们所能做的就是用承诺回报另一个未来,而这个未来是由第一个未来的结果来完成的

  val keylist = List("key1", "key2")

  val myFuts: List[Future[String]] = keylist.map {
    myid => {
      // this line simulates an external call which returns a future (retrieval from S3)
      val myfut = Future {
        Thread.sleep(1); "START " + myid
      }
      var mystr = "This should have been overwritten"
      val p = Promise[String]()
      myfut.onComplete {
        case Failure(ex) =>
          println(s"failed with error: $ex")
          mystr = "FAILED"
          p failure ex
        case Success(myval) =>
          mystr = s"SUCCESS $myid: $myval"
          println(mystr)
          p success myval
      }
      p.future
    }
  }

  val futset: Future[List[String]] = Future.sequence(myFuts)
  println(Await.result(futset, 10 seconds))
正如我在这里所问的,最方便的方法是mapAll方法:

我会避免使用
onComplete
并尝试使用它对可变变量执行副作用逻辑。相反,我将映射未来,并将失败案例处理为返回不同的值。下面是您的代码的一个稍加修改的版本,使用
Future
上的
map
(通过a进行理解),然后使用
recover
处理故障案例。希望这就是你一直在寻找的:

val keylist = List("key1", "key2")

val myFuts: List[Future[String]] = keylist.map {myid => 

  // this line simulates an external call which returns a future (retrieval from S3)
  val myfut = future { Thread.sleep(1); "START " + myid}
  val result = for (myval <- myfut) yield {
    val res = s"SUCCESS $myid: $myval"
    println(res)
    res
  }
  result.recover{
    case ex => 
      println (s"failed with error: $ex")
      "FAILED"          
  }

}

val futset: Future[List[String]] = Future.sequence(myFuts)
println (Await.result(futset, 10 seconds))
val keylist=List(“key1”、“key2”)
val myFuts:List[Future[String]=keylist.map{myid=>
//此行模拟一个外部调用,该调用返回未来(从S3检索)
val myfut=future{Thread.sleep(1);“START”+myid}
val结果=用于(myval)
println“失败,错误:$ex”)
“失败”
}
}
val futset:Future[List[String]=Future.sequence(myFuts)
println(等待结果(futset,10秒))

当我运行它时,它会超时并出现错误,但这是一个有趣的解决方案。我不明白“p”承诺是如何使用与任务相关的值来完成的。感谢帮助OOPS是的,添加了它。现在效果很好。很高兴看到使用承诺的解决方案!我一直在想,除了竞争性完成之外,它们还有什么用处.效果很好..recover方法是该模式的关键。我不知道有人能做到这一点。非常感谢!对于感兴趣的人,此答案和更有效的替代方法在中给出。
val keylist = List("key1", "key2")

val myFuts: List[Future[String]] = keylist.map {myid => 

  // this line simulates an external call which returns a future (retrieval from S3)
  val myfut = future { Thread.sleep(1); "START " + myid}
  val result = for (myval <- myfut) yield {
    val res = s"SUCCESS $myid: $myval"
    println(res)
    res
  }
  result.recover{
    case ex => 
      println (s"failed with error: $ex")
      "FAILED"          
  }

}

val futset: Future[List[String]] = Future.sequence(myFuts)
println (Await.result(futset, 10 seconds))