2013-07-18 39 views
34

我是斯卡拉期貨的新手,我對斯卡拉期貨的回報值有疑問。斯卡拉期貨返回的價值

所以,一般語法Scala的未來

def downloadPage(url: URL) = Future[List[Int]] { 

} 

我想知道的是如何從調用此方法其他方法訪問List[Int]

換句話說,

val result = downloadPage("localhost") 

那應該是讓List[Int]出未來的方法呢?

我一直在使用地圖的方法,但沒能做到這一點successfully.`

回答

7

你需要等待未來的完成得到給予一定的時間跨度,結果試了,這裏的東西,將工作:

import scala.concurrent.duration._ 

    def downloadPage(url: URL) = Future[List[Int]] { 
    List(1,2,3) 
    } 

    val result = downloadPage("localhost") 

    val myListInt = result.result(10 seconds) 

理想的情況下,如果您使用的是Future,你不想阻止執行的線程,所以你會移動你的邏輯與您Future的結果涉及到onComplete方法,像這樣:

result.onComplete({ 
    case Success(listInt) => { 
     //Do something with my list 
    } 
    case Failure(exception) => { 
     //Do something with my error 
    } 
    }) 
+3

我的問題是 result.onComplete({ 成功的情況下(listInt)=> {// 做一些與我的名單 } 萬一出現故障(異常)=> {// 做一些與我的錯誤 }} ) 會有一些方法的一部分,我想返回listInt值。怎麼做 ? – user1822249

+0

要麼返回自己,要麼阻塞,直到完成。 –

+0

你想,我建議'VAL myListInt = result.result(10秒)'雖然注意超時異常... – Noah

20

成功的例子(listInt)=>我想返回listInt,我無法弄清楚如何做到這一點。

最好的做法是,你不要返回值。相反,您只需將未來(或版本爲map,flatMap等)轉換爲需要此值的所有人,並且可以添加他們自己的onComplete

如果您確實需要返回它(例如,在實施傳統方法時),那麼您唯一能做的就是阻止(例如使用Await.result),並且您需要決定等待多久。

+1

因此,您無法無阻擋地返回未來的價值?我認爲斯卡拉的目標是成爲一個功能更強大的語言。如果未來回調返回單位,是否不支持副作用?有沒有辦法解決這個問題? –

+0

「所以你沒有辦法在沒有阻礙的情況下回報未來的價值?」你怎麼能?該值尚不可用。 「如果未來的回調回報單位,不支持副作用嗎?有沒有辦法解決這個問題?」使用'map','flatMap'等 –

+0

所以我特別的情況是檢查用戶會話是否有效。這樣做時,我向服務器發出請求以查看會話是否有效。我使用使用期貨的Play Framework WS庫。我只想能夠從isValidSession方法返回true或false,而不必阻塞線程。 –

4

我希望你已經解決了這一點,因爲有人問在2013年,但也許我的回答能幫助別人:

如果您正在使用播放框架,它支持異步操作(實際上所有的操作都是異步內)。創建異步操作的簡單方法是使用Action.async()。您需要爲此功能提供Future[Result]

現在,您只需使用Scala的地圖,flatMap,for-comprehension或async/await就可以從Future[List[Int]]Future[Result]進行轉換。這裏有一個來自Play Framework文檔的例子。

import play.api.libs.concurrent.Execution.Implicits.defaultContext 

def index = Action.async { 
    val futureInt = scala.concurrent.Future { intensiveComputation() } 
    futureInt.map(i => Ok("Got result: " + i)) 
} 
2

我發現想未來的最好辦法就是一個框,會在某一時刻,包含你想要的東西。 Future的關鍵在於你永遠不會打開盒子。試圖強行打開盒子會導致你阻塞和悲傷。相反,您將未來放在另一個更大的盒子中,通常使用地圖方法。

下面是包含字符串的Future的示例。未來完成時,然後控制檯。println被稱爲:

import scala.concurrent.Future 
import scala.concurrent.ExecutionContext.Implicits.global 

object Main { 

    def main(args:Array[String]) : Unit = { 
    val stringFuture: Future[String] = Future.successful("hello world!") 
    stringFuture.map { 
     someString => 
     // if you use .foreach you avoid creating an extra Future, but we are proving 
     // the concept here... 
     Console.println(someString) 
    } 
    } 
} 

請注意,在這種情況下,我們調用主要方法,然後...完成。字符串的Future由全局ExecutionContext提供,它執行調用Console.println的工作。這很好,因爲當我們放棄對someString將要到達的位置進行控制時,並且在調用Console.println時,我們讓系統自行管理。在constrast,看看會發生什麼,當我們試圖強行開盒子:

val stringFuture: Future[String] = Future.successful("hello world!") 
val someString = Future.await(stringFuture) 

在這種情況下,我們不得不等待 - 保持一個線程擺弄了大拇指 - 直到我們得到someString回來。我們已經打開了這個盒子,但我們不得不征服系統的資源來解決它。

2

你可以做那樣的事情。如果在Await.result方法給出的等待時間小於所花費的awaitable執行,你將有一個TimeoutException,你需要處理錯誤(或任何其他錯誤)。

import scala.concurrent._ 
import ExecutionContext.Implicits.global 
import scala.util.{Try, Success, Failure} 
import scala.concurrent.duration._ 

object MyObject { 
    def main(args: Array[String]) { 

     val myVal: Future[String] = Future { silly() } 

     // values less than 5 seconds will go to 
     // Failure case, because silly() will not be done yet 
     Try(Await.result(myVal, 10 seconds)) match { 
      case Success(extractedVal) => { println("Success Happened: " + extractedVal) } 
      case Failure(_) => { println("Failure Happened") } 
      case _ => { println("Very Strange") } 
     }  
    } 

    def silly(): String = { 
     Thread.sleep(5000) 
     "Hello from silly" 
     } 
}