对于您有一些简单的同步函数调用链的情况,您认为最好的scala解决方案是什么,并且您需要在其中间添加异步操作而不会阻塞?
我认为,期货需要重构现有代码以回调意大利面,将期货一直束缚在以前的同步函数调用链中,或者在每个区间轮询承诺,不是那么优化但是我可能缺少一些微不足道的/合适的选项在这里。
似乎对(akka)演员进行重构,需要大量的样板才能实现如此简单的工程技术。
如何在不阻塞的情况下插入现有同步流中的异步函数,而不需要进入大量样板文件?
现在在我的代码中我阻止了Await.result
,这只意味着一个线程正在睡觉......
答案 0 :(得分:1)
一个简单的肮脏技巧:
假设你有:
def f1Sync: T1
def f2Sync: T2
...
def fAsynchronous: Future[TAsync]
import scala.concurrent.{ Future, Promise }
object FutureHelper {
// A value class is much cheaper than an implicit conversion.
implicit class FutureConverter[T](val t: T) extends AnyVal {
def future: Future[T] = Promise.successful(t).future
}
}
然后你可以for yield
:
import FutureHelper._
def completeChain: Future[Whatever] = {
for {
r1 <- f1Sync.future
r2 <- f2Sync.future
.. all your syncs
rn <- fAsynchronous // this should also return a future
rnn <- f50Sync(rn).future// you can even pass the result of the async to the next function
} yield rn
}
将同步调用转换为立即解决的期货的模板很少。不要试图用Future.apply[T](t)
或简单Future(a)
这样做,因为这会将守护程序线程放到执行程序上。没有隐式执行器,您将无法转换。
凭借承诺,您可以支付3,4个承诺的价格,这些承诺可以忽略不计,您可以得到您想要的。 for yield
充当定序器,它将依次等待每个结果,因此您甚至可以在处理完异步结果后执行某些操作。
它将“等待”每个同步调用完成,这将立即通过设计发生,但async
调用将自动采用正常的异步处理。
答案 1 :(得分:1)
您也可以使用async / await库,但需要注意的是,您还需要处理一个大的未来:
http://docs.scala-lang.org/sips/pending/async.html
但是,它导致代码几乎与同步代码相同;你以前阻止的地方,你添加一个:
await { theAsyncFuture }
然后继续使用同步代码。