gpt4 book ai didi

scala - 对于理解: how to run Futures sequentially

转载 作者:行者123 更新时间:2023-12-04 13:59:13 26 4
gpt4 key购买 nike

给定以下方法...

def doSomething1: Future[Int] = { ... }
def doSomething2: Future[Int] = { ... }
def doSomething3: Future[Int] = { ... }

...以及以下理解:
for {
x <- doSomething1
y <- doSomething2
z <- doSomething3
} yield x + y + z

这三种方法并行运行,但是在我的情况下, doSomething2必须在 doSomething1完成之后运行。如何依次运行这三种方法?

编辑

Philosophus42所建议,以下是 doSomething1的可能实现:
def doSomething1: Future[Int] = {
// query the database for customers younger than 40;
// `find` returns a `Future` containing the number of matches
customerService.find(Json.obj("age" -> Json.obj("$lt" -> 40)))
}

...因此 Future是通过内部调用另一种方法创建的。

编辑2

也许我简化了用例……很抱歉。让我们再试一次,更接近实际用例。这是三种方法:
for {
// get all the transactions generated by the exchange service
transactions <- exchange.orderTransactions(orderId)

//for each transaction create a log
logs <- Future.sequence(tansactions.map { transaction =>
for {
// update trading order status
_ <- orderService.findAndUpdate(transaction.orderId, "Executed")

// create new log
log <- logService.insert(Log(
transactionId => transaction.id,
orderId => transaction.orderId,
...
))
} yield log
})
} yield logs

我想做的是为与订单关联的每个交易创建一个日志。即使 logService.insert仅包含一项, transactions也会被多次调用。

最佳答案

评论你的帖子

首先,doSomethingX中的代码是什么样的?更恼怒的是,使用您给定的代码, future 会并行运行。

回答

为了使Future执行顺序,只需使用

for {
v1 <- Future { ..block1... }
v2 <- Future { ..block2... }
} yield combine(v1, v2)

之所以起作用,是因为语句Future {..body ..}开始异步计算,在该时间点对该语句进行评估。

有了以上的领悟
Future { ..block1.. }
.flatMap( v1 =>
Future { ..block>.. }
.map( v2 => combine(v1,v2) )
)

很明显,
  • (如果Future{ ...block1... }可用),
  • 触发flatMap方法,其中
  • 然后
  • 触发Future { ...block2... }的执行。

  • 因此, Future { ...block2... }Future { ...block1... }之后执行

    附加信息
    Future
    Future { 
    <block>
    }

    立即通过ExecutionContext触发包含的块的执行

    片段1:
    val f1 = Future { <body> }
    val f2 = Future { <otherbody> }

    这两个计算正在并行运行(以这种方式设置ExecutionContext的情况),因为这两个值会立即求值。

    片段2:

    构造
    def f1 = Future { ..... }

    一旦调用f1,将开始执行 future

    编辑:

    j3d,我仍然感到困惑,为什么您的代码无法按预期运行,如果您的说法正确,那么Future 是在computeSomethingX方法的中创建的。

    这是证明computeSomething2computeSomething1之后执行的代码段

    导入scala.concurrent。{等待,将来}
    导入scala.concurrent.duration._
    object Playground {

    import scala.concurrent.ExecutionContext.Implicits.global

    def computeSomething1 : Future[Int] = {
    Future {
    for (i <- 1 to 10) {
    println("computeSomething1")
    Thread.sleep(500)
    }
    10
    }
    }

    def computeSomething2 : Future[String] = {
    Future {
    for(i <- 1 to 10) {
    println("computeSomething2")
    Thread.sleep(800)
    }
    "hello"
    }
    }

    def main(args: Array[String]) : Unit = {

    val resultFuture: Future[String] = for {
    v1 <- computeSomething1
    v2 <- computeSomething2
    } yield v2 + v1.toString

    // evil "wait" for result

    val result = Await.result(resultFuture, Duration.Inf)

    println( s"Result: ${result}")
    }
    }

    带输出
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething1
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    computeSomething2
    Result: hello10

    编辑2

    如果希望它们在并行中执行,请预先创建 future (此处为f1f2)
    def main(args: Array[String]) : Unit = {
    val f1 = computeSomething1
    val f2 = computeSomething2

    val resultFuture: Future[String] = for {
    v1 <- f1
    v2 <- f2
    } yield v2 + v1.toString

    // evil "wait" for result

    val result = Await.result(resultFuture, Duration.Inf)

    println( s"Result: ${result}")
    }

    关于scala - 对于理解: how to run Futures sequentially,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32374074/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com