2017-02-20 71 views
0

我有它返回一個字符串,如下所示的阿卡HTTP服務:爲什麼我的地圖()不工作?

val route1: Route = { 
    path("hello") { 
     get{ 
     complete{ 
      println("Inside r1") 
      "You just accessed hello" 
     } 
     } 
    } 
} 

我想了解地圖和flatMap

例如之間的差別,下面的代碼給我的結果作爲預計:

val future1: Future[String] = 
    Http() 
    .singleRequest(
     HttpRequest(method = HttpMethods.GET, 
        uri = "http://localhost:8187/hello")) 
    .flatMap(testFlatFunc) 

def testFlatFunc(x: HttpResponse): Future[String] = { 
    Unmarshal(x).to[String] 
} 

但是,如果我試圖用地圖來取代它,下面我得到的輸出爲FulfilledFuture(You just accessed hello)

val future1: Future[String] = Http() 
    .singleRequest(
     HttpRequest(method = HttpMethods.GET, 
        uri = "http://localhost:8187/hello")) 
    .map(testFunc) 

def testFunc(x: HttpResponse): String={ 
    Unmarshal(x).to[String].toString 
} 

爲什麼我的map()不能按預期工作?

回答

1

這是關於你的testFunc做什麼:

def testFunc(x: HttpResponse): String = { 
    Unmarshal(x).to[String].toString 
} 

這裏的類型是好的,但你在裏面做的不是。

Unmarshal(x).to[String] 

回報Future[String] - 這意味着它是異步的結果,它的價值會在第一時間出現在那裏。沒關係,在flatMap中使用這樣的結果類型。

val sqrts: Double => List[Double] = x => List(Math.sqrt(x), -Math.sqrt(x)) 
val numbers = List(4.0, 9.0, 16.0) 
numbers.flatMap(sqrts) // List(2.0, -2.0, 3.0, -3.0, 4.0, -4.0) 
// results equal to 
numbers 
    .map(sqrts) // List(List(2.0, -2.0), List(3.0, -3.0), List(4.0, -4.0)) 
    .flatten // List(2.0, -2.0, 3.0, -3.0, 4.0, -4.0) 

在這裏你可以看到,flatMap就像地圖+扁平化(除了某些容器​​甚至沒有已經實現扁平化,例如Future;))。

但爲什麼您的testFunc失敗?基本上,你採取異步結果(Future[String]),你不等待結果 - 你調用toString而不是隻打印一些無用的信息(FulfilledFuture(You just accessed hello)),但不是結果本身。

要解決這一點,你就必須這樣做:

def testFunc(x: HttpResponse): String = { 
    Await.result(Unmarshal(x).to[String], 10.seconds) 
} 

這將阻止,最多等待10秒鐘,結果,使之同步。(在這種情況下,這種方式勝過目的,如果您計算的結果首先是同步的,則map會更有用。)

1

mapflatMap區別:

flatMap就會崩潰嵌套結構的一個級別(它調用fallten),如:List(List(1), List(2)).flatMap(i => i)將是:List(1, 2)

使你的代碼,testFlatFunctestFunc退貨類型Future[String]mapflatMap函數的返回類型也是Future[T],但是flatMap會使巢結構變平,所以:Future[Future[String]]會變平爲Future[String]。和map功能將無法做到這一點,所以:

val future1:Future[String] = Http() 
    .singleRequest(
     HttpRequest(method = HttpMethods.GET, 
        uri = "http://localhost:8187/hello")).map(testFunc) 

返回類型應該是:

val future1:Future[Future[String]] = Http() 
    .singleRequest(
     HttpRequest(method = HttpMethods.GET, 
        uri = "http://localhost:8187/hello")).map(testFunc)