[英]How to use Scala ARM with Futures?
我想實現ARM(自動資源管理)模式,其中資源是異步使用的。
假設我的資源看起來像:
class MyResource {
def foo() : Future[MyResource] = ???
// Other methods returning various futures
def close() : Unit = ???
}
object MyResource {
def open(name: String): Future[MyResource] = ???
}
所需的使用模式是:
val r : Future[MyResource] = MyResource.open("name")
r flatMap (r => {
r.foo() /* map ... */ andThen {
case _ => r.close()
}
})
省略的映射函數可能很復雜,涉及分支和鏈接期貨,這些期貨會重復調用返回期貨的r
方法。
我想確保在所有未來的延續完成(或失敗)之后調用r.close()
)。 在每個呼叫站點手動執行此操作非常容易出錯。 這需要ARM解決方案。
scala-arm庫通常是同步的。 這段代碼不會做正確的事情,因為在塊內的期貨完成之前會調用close():
for (r <- managed(MyResource.open("name"))) {
r map (_.foo()) // map ...
}
我雖然使用這個包裝器:
def usingAsync[T](opener: => Future[MyResource]) (body: MyResource => Future[T]) : Future[T] =
opener flatMap {
myr => body(myr) andThen { case _ => myr.close() } }
然后呼叫站點看起來像:
usingAsync(MyResource.open("name")) ( myr => {
myr.foo // map ...
})
但是,塊中的代碼將負責返回在該塊創建的所有其他期貨完成時完成的Future。 如果它意外沒有,那么資源將在所有使用它的期貨完成之前關閉。 並且沒有靜態驗證來捕獲此錯誤。 例如,這將是一個運行時錯誤:
usingAsync(MyResource.open("name")) ( myr => {
myr.foo() // Do one thing
myr.bar() // Do another
})
顯然,我可以使用scala-arm的分隔連續支持(CPS)。 它看起來有點復雜,我害怕弄錯。 它需要啟用編譯器插件。 此外,我的團隊對scala非常陌生,我不想要求他們使用CPS。
CPS是前進的唯一途徑嗎? 是否有一個圖書館或設計模式可以更簡單地使用Futures,或者使用scala-arm執行此操作的示例?
Reactive Extensions(Rx)可能是另一種解決方案。 圍繞這種編程范式的勢頭越來越大,現在有許多語言可供使用,包括Scala。
Rx的基礎是創建一個Observable,它是異步事件的來源。 Observable可以用復雜的方式鏈接,這就是它的力量。 您訂閱了一個Observable來監聽onNext,onError和onComplete事件。 您還會收到允許您取消訂閱的訂閱。
我想你可能會在onCompleted和/或onError處理程序中添加一個resource.close()調用。
請參閱RxScala文檔:
Observable.subscribe(
onNext: (T) ⇒ Unit,
onError: (Throwable) ⇒ Unit,
onCompleted: () ⇒ Unit): Subscription
更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.