在Scala中的简单同步流中混合异步代码

时间:2015-03-04 19:07:10

标签: scala asynchronous

对于您有一些简单的同步函数调用链的情况,您认为最好的scala解决方案是什么,并且您需要在其中间添加异步操作而不会阻塞?

我认为,期货需要重构现有代码以回调意大利面,将期货一直束缚在以前的同步函数调用链中,或者在每个区间轮询承诺,不是那么优化但是我可能缺少一些微不足道的/合适的选项在这里。

似乎对(akka)演员进行重构,需要大量的样板才能实现如此简单的工程技术。

如何在不阻塞的情况下插入现有同步流中的异步函数,而不需要进入大量样板文件?

现在在我的代码中我阻止了Await.result,这只意味着一个线程正在睡觉......

2 个答案:

答案 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 } 

然后继续使用同步代码。