2013-04-05 79 views
11

考虑下面的例子:我该如何将这个未来的结构扁平化?

val handler : Connection = new DatabaseConnectionHandler() 
    val result : Future[Future[Future[Option[ResultSet]]]] = handler.connect 
    .map((parameters) => handler) 
    .map(connection => connection.sendQuery("BEGIN TRANSACTION SERIALIZABLE")) 
    .map(future => future.map(query => query.rows)) 
    .map(future => handler.sendQuery("COMMIT").map(query => future)) 

是否有可能将其平整接收Future[Option[ResultSet]]在最后,而不是未来几年内这个未来Scala中的一个未来结构里面?

我目前正在使用斯卡拉的2.10未来的和承诺的,但我找不到一个方法来解决这个问题。我知道我可以使用嵌套回调,但我宁愿避免这种情况,因为代码看起来很可怕。

Connection特征定义为here

回答

22

无论何时你map与论点类型A => Future[B]你应该真的使用flatMap。然后

的代码会是这样的:

val connection : Connection = new DatabaseConnectionHandler(DefaultConfiguration) 
    val result: Future[QueryResult] = connection.connect 
    .flatMap(_ => connection.sendQuery("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ")) 
    .flatMap(_ => connection.sendQuery("SELECT 0")) 
    .flatMap(_ => connection.sendQuery("COMMIT").map(value => query)) 

或者,你可以使用-理解。 It uses flatMap for you

val connection : Connection = new DatabaseConnectionHandler(DefaultConfiguration) 
val result: Future[QueryResult] = for { 
    _ <- connection.connect 
    _ <- connection.sendQuery("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ") 
    _ <- connection.sendQuery("SELECT 0") 
    queryResult <- connection.sendQuery("COMMIT").map(value => query) 
} yield { queryResult } 
+0

不错,就是这样! – 2013-04-05 14:21:05

+2

'scala.concurrent.Future'没有'flatten'' – senz 2015-05-13 09:33:22

+2

@senz是的,'scala.concurrent.Future'没有'flatten'。但是你可以使用'f flatMap identity'。 [见这里](https://groups.google.com/forum/#!topic/scala-internals/yVYe_xnUOFA) – HEX 2015-09-07 11:18:59

8

您应该使用flatMap代替map这里。

flatMap需要一个功能fun返回未来g并返回未来h从未来g拿着值fun返回。

此外,请考虑写在for -comprehension内,请参阅here

+0

感谢您的回答:) – 2013-04-05 14:26:36