gpt4 book ai didi

scala - 将多个 WS 调用合并为一个结果时处理错误

转载 作者:行者123 更新时间:2023-12-04 05:30:48 27 4
gpt4 key购买 nike

我正在同时学习 scala、play 和 web 服务,所以请耐心等待。我已经建立了一个小聚合服务,它结合了天气网络服务和谷歌的地理编码和地点网络服务。我有一些工作,但我对处理错误的正确方法有点困惑。 (我把代码贴在文末)

所以地方 api 使用纬度/经度,所以我使用地理编码 api 从邮政编码中获取纬度/经度。在处理对地理编码 api 的调用的响应时,我最终得到一个 (Option[String], Option[String]) (保存在 maybeLoc val 中)。在检查 maybeLoc 的匹配语句中, 如果它最终是 (None, None) , 我返回 Promise()因为我需要返回 Promise从平面图调用。

我对此有两个问题:

1.) 在这些 flatMap 或 map 调用之一中处理无法进行任何进一步处理的情况的正确方法是什么?它要求我返回一个 promise ,但做一个空的 Promise当我去赎回时,这将只是超时,这似乎是一个非常糟糕的主意。

2.) 我假设对 Promise() 的调用是否正确?制作一个空的 promise 对象,在尝试赎回它时总是会超时?我真的无法从 scaladoc 中分辨出来,也无法从谷歌找到任何关于它的信息。

我希望我的问题对你有意义并且足够清楚。这是代码:

def bothAsJson(zipcode:String) = Action {
val promiseOfLoc = Geocode.buildUrlFor(zipcode).get()
val promiseOfWeather = Weather.buildUrlFor(zipcode, "json").get()

val result = promiseOfLoc.flatMap { locResp =>
val maybeLoc = Geocode.extractLocation(locResp.body.toString())
maybeLoc match {
case (Some(lat), Some(lng)) => {
val promiseOfPlaces = Places.buildUrlFor(lat,lng).get()
promiseOfPlaces.flatMap { placesResp =>
promiseOfWeather.map { weatherResp =>
(weatherResp.body.toString(), placesResp.body.toString())
}
}
}
case _ => Promise()
}
}

Async {
result.orTimeout("Timeout!", 2000).map {response =>
response.fold(
result => Ok("Got:\n\nweather:\n" + result._1 + "\n\nplaces:\n" + result._2),
timeout => InternalServerError(timeout)
)
}
}
}

最佳答案

如果你得到 (None, None) 你不应该期待超时,但我相信会返回另一条错误消息。我在下面提供了一个示例。

我认为您需要来自 scalaz 7 的 OptionT。我将其写为:

import scalaz._
import Scalaz._

def bothAsJson(zipcode:String) = Action {
val promiseOfLoc = Geocode.buildUrlFor(zipcode).get.map { Option(_.body.toString()) }
val promiseOfWeather = Weather.buildUrlFor(zipcode, "json").get
.map{ lockResp =>
val (lat,lng) = Geocode.extractLocation(locResp.body.toString())
(lat |@| lng).tupled
}
def buildPlaces(lat: String, lng: String) = Places.buildUrlFor(lat,lng).get
.map { Option(_.body.toString) }

val result = (for {
(lat, lng) <- OptionT(promiseOfLoc)
places <- OptionT(Places.buildUrlFor(lat,lng).get())
weather <- OptionT(promiseOfWeather)
} yield (places, weather)).run

Async {
result.orTimeout("Timeout!", 2000).map {response =>
response.fold(
result => {
result.map(
some => Ok("Got:\n\nweather:\n" + some._1 + "\n\nplaces:\n" + some._2)
).getOrElse(BadRequest("lat/lng failed probably?"))
},
timeout => InternalServerError(timeout)
)
}
}
}

OptionT我们可以将它作为 Option 进行平面映射,如果我们得到一个 None ,则获得不处理任何东西的能力。最后我们留下了 Promise[Option[T]]这是非常好的。处理错误的另一种好方法是将 Either/EtherT 与相同的方法一起使用。
|@|是一个应用生成器。它需要 2 个选项,并返回 Option((Int, Int))如果双方都是 Some .如果一侧或两侧是 None ,它返回一个 None .

请注意,要使其正常工作,您需要一个 scalaz Monad[Promise]实例
implicit val PromiseInstance = new Monad[Promise] {
// override def map[A,B](fa: Promise[A])(f: A => B) = fa.map(f)
def point[A](a: => A) = Promise.pure(a)
def bind[A,B](fa: Promise[A])(f: A => Promise[B]) = fa.flatMap(f)
}

另请注意,我已经在 SO 编辑器中编写了所有这些代码,可能缺少大括号。但是所有的代码应该或多或少是正确的,我在 repl 中测试了它的一部分。

请随时在 freenode irc 上的 #scalaz 或 scalaz google 群组上寻求帮助。

关于scala - 将多个 WS 调用合并为一个结果时处理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12666169/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com