【问题标题】:Why is my map() not working?为什么我的 map() 不起作用?
【发布时间】:2017-07-09 06:50:21
【问题描述】:

我有一个 Akka HTTP 服务,它返回一个字符串,如下所示:

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

我正在尝试了解 map 和 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() 没有按预期工作?

【问题讨论】:

    标签: scala future akka-http spray-client


    【解决方案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 的工作方式类似于 map + flatten(除了某些容器​​甚至不必实现 flatten,例如 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 会更有用。)

    【讨论】:

      【解决方案2】:

      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)
      

      【讨论】:

        猜你喜欢
        • 2012-07-30
        • 2016-07-14
        • 2018-05-31
        • 1970-01-01
        • 1970-01-01
        • 2015-09-25
        • 2018-03-05
        • 2013-04-19
        • 2015-10-17
        相关资源
        最近更新 更多