为什么我的 map() 不工作?
Why is my map() not working?
我有一个Akka HTTP服务,其中returns一个字符串,如下图:
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() 没有按预期工作?
map
和flatMap
区别:
flatMap
will collapse one level of nested structure(it calls fallten), like: List(List(1), List(2)).flatMap(i => i)
will be: List(1, 2)
所以对于您的代码,testFlatFunc
和 testFunc
return 类型 是 Future[String]
,并且 map
flatMap
函数 return 的类型也是 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)
return 类型应该是:
val future1:Future[Future[String]] = Http()
.singleRequest(
HttpRequest(method = HttpMethods.GET,
uri = "http://localhost:8187/hello")).map(testFunc)
这是关于你在 testFunc
中所做的事情:
def testFunc(x: HttpResponse): String = {
Unmarshal(x).to[String].toString
}
这里的类型可以,但是你在里面做的就不行了。
Unmarshal(x).to[String]
returns 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
会更有用。)
我有一个Akka HTTP服务,其中returns一个字符串,如下图:
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() 没有按预期工作?
map
和flatMap
区别:
flatMap
will collapse one level of nested structure(it calls fallten), like:List(List(1), List(2)).flatMap(i => i)
will be:List(1, 2)
所以对于您的代码,testFlatFunc
和 testFunc
return 类型 是 Future[String]
,并且 map
flatMap
函数 return 的类型也是 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)
return 类型应该是:
val future1:Future[Future[String]] = Http()
.singleRequest(
HttpRequest(method = HttpMethods.GET,
uri = "http://localhost:8187/hello")).map(testFunc)
这是关于你在 testFunc
中所做的事情:
def testFunc(x: HttpResponse): String = {
Unmarshal(x).to[String].toString
}
这里的类型可以,但是你在里面做的就不行了。
Unmarshal(x).to[String]
returns 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
会更有用。)