这是我之前question
的后续内容假设我想用我的函数创建一个未来,但不想立即启动它(即我不想调用val f = Future { ... // my function}
。
现在我看到它可以按如下方式完成:
val p = promise[Unit] val f = p.future map { _ => // my function here }
这是使用我的函数创建未来的唯一方法吗?
答案 0 :(得分:6)
你可以做这样的事情
val p = Promise[Unit]()
val f = p.future
//... some code run at a later time
p.success {
// your function
}
LATER EDIT:
我认为您正在寻找的模式可以像这样封装:
class LatentComputation[T](f: => T) {
private val p = Promise[T]()
def trigger() { p.success(f) }
def future: Future[T] = p.future
}
object LatentComputation {
def apply[T](f: => T) = new LatentComputation(f)
}
您可以这样使用它:
val comp = LatentComputation {
// your code to be executed later
}
val f = comp.future
// somewhere else in the code
comp.trigger()
答案 1 :(得分:3)
你总是可以用一个闭包推迟创建,你不会提前获得未来的对象,但是你可以稍后调用它。
type DeferredComputation[T,R] = T => Future[R]
def deferredCall[T,R](futureBody: T => R): DeferredComputation[T,R] =
t => future {futureBody(t)}
def deferredResult[R](futureBody: => R): DeferredComputation[Unit,R] =
_ => future {futureBody}
答案 2 :(得分:2)
如果你对执行控制过于谨慎,也许你应该使用演员?
或者,或许,您应该使用Promise
而不是Future
:Promise
可以传递给其他人,同时您可以将其保持在“履行”状态。以后的时间。
答案 3 :(得分:2)
同样值得给Promise.completeWith
插件。
您已经知道如何使用p.future onComplete mystuff
。
您可以使用p completeWith f
从其他未来触发。
答案 4 :(得分:2)
您还可以定义一个创建并返回Future的函数,然后调用它:
val double = (value: Int) => {
val f = Future { Thread.sleep(1000); value * 2 }
f.onComplete(x => println(s"Future return: $x"))
f
}
println("Before future.")
double(2)
println("After future is called, but as the future takes 1 sec to run, it will be printed before.")
我用它来批量执行n个期货,例如:
// The functions that returns the future.
val double = (i: Int) => {
val future = Future ({
println(s"Start task $i")
Thread.sleep(1000)
i * 2
})
future.onComplete(_ => {
println(s"Task $i ended")
})
future
}
val numbers = 1 to 20
numbers
.map(i => (i, double))
.grouped(5)
.foreach(batch => {
val result = Await.result( Future.sequence(batch.map{ case (i, callback) => callback(i) }), 5.minutes )
println(result)
})
答案 5 :(得分:1)
或者只使用返回期货的常规方法,并使用类似于理解(顺序调用现场评估)之类的方式将它们串联起来
答案 6 :(得分:1)
标准库的这个众所周知的问题未来:它们的设计方式使得它们不是引用透明的,因为它们急切地评估并记住它们的结果。在大多数用例中,这完全没问题,Scala开发人员很少需要创建未评估的未来。
采取以下计划:
val x = Future(...); f(x, x)
与
的程序不同f(Future(...), Future(...))
因为在第一种情况下,未来被评估一次,在第二种情况下,它被评估两次。
这些库提供必要的抽象来处理引用透明的异步任务,除非开发人员明确要求,否则其评估将被推迟并且不会被记忆。
如果你想使用Cats,Cats效果可以很好地适用于Monix和fs2。
答案 7 :(得分:1)
这有点骇人听闻,因为它与未来的工作方式无关,而仅添加懒惰就足够了:
// Call function
addWatermark(inputURL: videoURL! as URL, outputURL: videoURL! as URL, handler: @escaping ()-> Void)
但是请注意,这也是一种类型更改,因为每当您引用它时,都需要将引用声明为惰性的,否则它将被执行。