2017-03-10 57 views
0

我試圖從代碼片段中獲取結果爲Future的值,但是當我運行代碼時,事實證明,它永遠不會輸入onComplete函數。有什麼我做錯了嗎?Scala未進入onComplete()

我使用地圖嘗試,以及因爲它是在其他職位的建議,但還沒有成功

override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = { 

     //query for customer in db 
     val avroCustomer: Future[AvroCustomer] = customerByPhone(phoneNumber) 

     avroCustomer.onComplete({ 
     case Success(null) => { 
      createUserAndEvent(phoneNumber, creationReason, 1.0) 
     } 

     case Success(customer) => { 
      Future.successful(customer) 
     } 

     case Failure(exception) => { 

     } 
}) 
+0

你等待'Future'到完成在調用此代碼的代碼中運行?你是否可能會遇到「失敗」並忽略它? – jkinkead

+1

也許你的未來實際上並沒有完成很長一段時間。您可能希望嘗試'Await.result'進行調試。 – francoisr

+1

期貨在那裏是最終的 - >你必須在@jkinkead指出的某個時刻等待它們。如果您在程序結束時運行「Future」,並且不等它,您將永遠不會看到結果。 – sebszyller

回答

2

回答對評論擴大。這個虛擬程序不會打印任何東西。

import scala.concurrent.Future 
import scala.util.{Failure, Success} 
import scala.concurrent.ExecutionContext.Implicits.global 

object Quickie { 
    def main(args: Array[String]): Unit = { 
    val addOneInFuture: Future[Int] = Future(addOne(3)) 

    addOneInFuture.onComplete { 
     case Success(s) => println(s) 
     case Failure(ex) => println(ex.toString) 
     case _ => println("what the hell happened") 
    } 

    } 

    def addOne(x: Int): Int = x + 1 
} 

我火了一個新的線程,但由於一點也沒有所需要的價值,我不會看到印有4。但是,添加一個簡單的AwaitThreed.sleep(_eternity_),赫克甚至是另一個println,你會看到結果。有一點需要了解的是Scala中的Futures是你想把它們作爲集合(因此它們有for-comprehensions),並且你很少想要做某件事情並且打印。如果你做了一些數據庫或者休息IO,你將會進一步處理數據。

Daniel Westheide有一個古老的黃金博客系列,你可以閱讀。 http://danielwestheide.com/blog/2013/01/09/the-neophytes-guide-to-scala-part-8-welcome-to-the-future.html

1

伊莫,而不是使用的onComplete,你想要什麼,這將不會返回(的onComplete是Unit類型的方法),首先,你可以嘗試捕捉異常的DB側,無論是與一個嘗試的類型或恢復,然後讓你的方法返回Option[AvroCustomer]

這是scala的完美用例可選的包裝類型(使用空類型的Scala-tastic方法)。如果customerByPhone由於某種原因返回null,那麼可以在db函數端捕獲它並將其轉換爲可選類型。

即,速度非常快,如果它是一個可空類型:

def customerByPhone(s: String) = { 
    ... //Some code 
    db.run(query).map(Option(_)) 
} 

現在這產生Option[avroCustomer]然後你就可以連鎖這種方式:

override def findOrCreate(phoneNumber: String, creationReason: String): Future[AvroCustomer] = { 

     //query for customer in db 
     customerByPhone(phoneNumber).flatMap { 
     case Some(customer) => Future.successful(customer) 

     case None => createUserAndEvent(phoneNumber, creationReason, 1.0) //I'm assuming this returns a futures. 
     } 
}