处理Scala中的多个期货

时间:2014-08-27 03:39:59

标签: scala future

我目前有一种方法可以根据Future[String]更新Redis表。

  def update(key: String, timeStamp: Long, jsonStringF: Future[String], redisClient: RedisClient) = {

    jsonStringF.map { jsonString =>
      val historyKey = "history." + key
      val tempKey = "temp." + key

      val tran = redisClient.transaction()
      tran.zadd(historyKey, (timeStamp, jsonString))
      tran.del(tempKey)
      val f = tran.exec()
      f.onComplete {
        case Success(suc) => dlogger.info(s"Updated $historyKey and deleted $tempKey successfully ....")
        case Failure(ex) => dlogger.warn(s"Error updating tables", ex)
      }
    }
  } 

现在我有两个Future[String]jsonStringF1jsonStringF2),我想更新两个不同的表格。

  def update(key: String, timeStamp: Long, jsonStringF1: Future[String], jsonStringF2: Future[String], redisClient: RedisClient) = {
 ....

}

我想在"another." + key中使用String更新另一个表格jsonStringF2)。我怎样才能做到这一点 ?

更新:以下代码是否正确?

  def update(tableKey: String, timeStamp: Long,  jsonStringF1: Future[String], jsonStringF2: Future[String], redisClient: RedisClient) =
  {

    for {
      a <- jsonStringF1
      t <- jsonStringF2

      historyKey = "history." + tableKey
      anotherKey = "another." + tableKey + 

      tempKey = "temp." + tableKey
      tran = redisClient.transaction()
      _ = tran.zadd(historyKey, (timeStamp, a))
      _ = tran.zadd(anotherKey, (timeStamp, t))
      _ = tran.del(tempKey)
      f = tran.exec()
    } yield ()
  }

3 个答案:

答案 0 :(得分:3)

您可以使用for收集多个期货:

val f1: Future[String] = ...
val f2: Future[String] = ...

for {
  a <- f1
  b <- f2
} {
  // Code to execute when both f1 and f2 complete
  // a and b are available here
}

答案 1 :(得分:3)

  1. 您可以使用进行循环,如您所述

    def update(tableKey: String, timeStamp: Long,  jsonStringF1: Future[String], jsonStringF2:Future[String], redisClient: RedisClient) = {
        for {
            a <- jsonStringF1
            t <- jsonStringF2
        } yield {
            val historyKey = "history." + tableKey
            val anotherKey = "another." + tableKey
    
            val tran = redisClient.transaction()
            tran.zadd(historyKey, (timeStamp, a))
            tran.zadd(anotherKey, (timeStamp, t))
            tran.del(tempKey)
            tran.exec()
        }
    }
    
  2. 作为 for 的替代方法,您还可以使用scala / async(https://github.com/scala/async)并编写代码,如下所示

    def update(tableKey: String, timeStamp: Long,  jsonStringF1: Future[String], jsonStringF2:Future[String], redisClient: RedisClient) = {
        async {
            val a = await(jsonStringF1)
            val t = await(jsonStringF2)
    
            val historyKey = "history." + tableKey
            val anotherKey = "another." + tableKey
    
            val tran = redisClient.transaction()
            tran.zadd(historyKey, (timeStamp, a))
            tran.zadd(anotherKey, (timeStamp, t))
            tran.del(tempKey)
            tran.exec()
        }
    }
    
  3. 哪个也是非阻塞的。 由于

    ,Async略有优势
      

    异步块被编译为单个匿名类,而不是a   为每个生成器所需的每个闭包分开匿名类。

答案 2 :(得分:0)

由于您只有2个期货,您可以压缩它们:

def update(tableKey: String, timeStamp: Long,  jsonStringF1: Future[String], jsonStringF2:Future[String], redisClient: RedisClient) = {

    val jsons = jsonStringF1.zip(jsonStringF2)
    jsons map {
      case (a, t) => 
        val historyKey = "history." + tableKey
        val anotherKey = "another." + tableKey

        val tran = redisClient.transaction()
        tran.zadd(historyKey, (timeStamp, a))
        tran.zadd(anotherKey, (timeStamp, t))
        tran.del(tempKey)
        tran.exec()
    }
}