虽然组合期货具有收益率结构,有些具有副作用,有些没有,我引入了竞争条件,因为取决于副作用的未来不会将该方面的结果影响未来作为论据。
简而言之:
未来 b 会读取未来因副作用而更改的值 a ,但未来 a 并未明确依赖于未来 b 的结果,因此可能会在 b 结束之前发生读数。
为了解决这个问题,我的同事介绍了一个虚拟函数,将 b 的结果作为参数,并简单地将其丢弃。这样做是为了使依赖显式化。
实际代码在这里:
val futureConnection:Future[(Either[String, (Connection)],Boolean)] =
for {
scannerUser <- scanner.orFail("Scanning user not found")
scannedUser <- futureScannedUser.orFail("Scanned user not found")
existsInAnyDirection <- connections.existsInAnyDirection(scannerUser, scannedUser)
connection <- connections.createConnection(scannerUser, scannedUser, form.magicWord, existsInAnyDirection)
} yield {
(connection, existsInAnyDirection)
}
在这种情况下,未来 b 是
connections.existsInAnyDirection(scannerUser, scannedUser)
和未来 a 是
connections.createConnection(scannerUser, scannedUser, form.magicWord, existsInAnyDirection)
请注意,existsInAnyDirection
中永远不会使用参数createConnection
。这有效地创建了依赖关系图,在existsInAnyDirection完成之前无法启动createConnection。
现在提出问题:
奖励信息
我自己的挖掘告诉我,Scala Futures根本不能很好地处理副作用。处理副作用的The methods on the Future trait返回单位,而从副作用操作中读取的结果很可能,即错误代码,生成的ID,任何其他元信息,真的。
答案 0 :(得分:0)
Future
正在处理推迟计算的副作用,如A => Future[B]
。
您试图混合几种不同的副作用,但只组成其中一种Future[_]
。
尝试选择第二个容器,这可以是产品或状态,取决于你的副作用,并考虑组成副作用(可能你需要modand变形金刚)。在您的代码看起来像(最简单的情况)之后:
for {
scannerUser <- scanner.orFail("Scanning ...")
(scannedUser, magicWord) <- futureScannedUser.orFail("Scanned ...")
connection <- connections.createConnection(scannerUser, scannedUser, magicWord)
} yield {
(connection, existsInAnyDirection)
}
// OR
for {
(scannerUser, state) <- scanner.orFail("Scanning ...")
(scannedUser, nextState) <- futureScannedUser(state).orFail("Scanned ...")
connection <- connections.createConnection(scannerUser, scannedUser, nextState)
} yield {
(connection, existsInAnyDirection)
}