如何在Scala中整理多个Future对象的OnSuccess

时间:2016-12-28 12:57:01

标签: scala

以下代码使用print语句模拟在线购物。我正在使用Future来模拟我同时向购物篮添加多个项目的场景(我在篮子中添加每个偶数项目)。我最后想要的是,代码会打印出已添加到篮子中的项目数量。

  1. 我创建了5个Future对象(所以我希望结果为5)
  2. 我将每个Future存储在List中。
  3. 我使用for循环等待每个Future的完成
  4. 我希望在所有期货执行完毕后,我会选择他们的 成功对象并整理它们的值(添加它们)。这是一部分 我无法编码。

    import scala.concurrent._
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.util.{Failure,Success}
    
    
    object ConcurrencyExample extends App {
    
      //simulation of backend process of adding an object in basket
      def addToBaskset(id:Int): Future[Int] = {
        Future {
          println("adding item "+id+" to shopping basket")
          Thread.sleep(10) //simulate backend process delay
          println("Item "+ id +" added")
          1 //simulate the no. of items in basket
        }
      }
    
      //simulate shopping. Pick even numbers and add them to baskset
      def simulateShopping(count:Int):List[Future[Int]] = {
        def go(c:Int, l:List[Future[Int]]):List[Future[Int]] = {
          println("looking at more items in inventory ")
          if(c == 0) l else
          if (c % 2 == 0)
          {
            Thread.sleep(10)
            go(c-1,addToBaskset(c)::l)
          }
          else {
            Thread.sleep(10)
            go(c-1,l)
          }
        }
        go(10,List())
      }
    
    
      val time = System.currentTimeMillis()
      val shoppingList: List[Future[Int]] = List()
    
      println("start shopping...")
      //simulate shopping of 10 items. Even values will be added to basket using Future. Return list of Future created
      val futures:List[Future[Int]] = simulateShopping(10)
    
      //wait for each item in list to finish. Its results will be collected in a new list called 'result'
      val result = for (i<- futures) yield i //we will get Success(1), 5 times
    
      println("finished shopping. result: " +result)
    
      **//how to I get a single integer value which is sum of all Success values?**
    //result seem to be a  List of Success() (not Future), so I tried using foldLeft or map but the code doesn't compile if I use them. I keep getting error for Unit value.
    
    
    }
    
  5. 结果

    start shopping...
    looking at more items in inventory 
    looking at more items in inventory 
    adding item 10 to shopping basket
    Item 10 added
    looking at more items in inventory 
    adding item 8 to shopping basket
    looking at more items in inventory 
    Item 8 added
    looking at more items in inventory 
    looking at more items in inventory 
    adding item 6 to shopping basket
    Item 6 added
    looking at more items in inventory 
    adding item 4 to shopping basket
    looking at more items in inventory 
    Item 4 added
    looking at more items in inventory 
    looking at more items in inventory 
    adding item 2 to shopping basket
    Item 2 added
    looking at more items in inventory 
    finished shopping. result: List(Success(1), Success(1), Success(1), Success(1), Success(1))
    

    处理完成,退出代码为0

    以下代码似乎有效,但为什么我必须在打印显示成功(1)时将结果元素视为Future [Int]?

    //y seem to be Future[Int]
    //y.value is Option(Success(1))
    //v.get is calling 'get' on Success
    val total = result.foldLeft(0)((x,y)=>y.value match {
        case Some(v)=>x+v.get
        case None=>x
      })
      println("finished shopping. result: " +result + "total "+total)
    
    
    finished shopping. result: List(Success(1), Success(1), Success(1), Success(1), Success(1))total 5
    

2 个答案:

答案 0 :(得分:1)

您可以使用Future.sequenceList[Future[Int]]转为Future[List[Int]],然后拨打sum以查看所有项目已添加:

val result: Int = Await.result(Future.sequence(futures).map(_.sum), 5 seconds)

请注意,Await.result仅用于在未完成所有期货的情况下不会提前终止测试。

  

为什么我必须将结果元素视为Future [Int]   打印显示他们是成功的(1)?

由于Future[T].value返回Option[Try[T]],其中Try可以是SuccessFailure。但是如果未来完成,它只会返回一个值。我根本不会使用.value

答案 1 :(得分:1)

Future.foldLeft(futures)(0)(_ + _).foreach(result => "finished shopping. result: " +result)