您好,登錄后才能下訂單哦!
本篇內容介紹了“STTP的基本使用方法是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
如果使用 AkkaHttp 作為 STTP 的 backend 來并發地處理 list of url,就會得到類似 List[Future[Response[Either[ResponseError[io.circe.Error], T]]]],這樣的結果。
一般地,我們更期望給上層調用者返回 Future[(List[Exception], List[T])]這樣的類型。
下面代碼演示了如何把:
List[Future[Response[Either[ResponseError[io.circe.Error], NasaData]]]]
準換為
Future[(List[Throwable], List[NasaData])]。
其中 tuple 的第一部分表示 response 中所有的 exception,第二部分表示所有正常數據。
幾個技術關鍵點是:
1)Future.sequence 用于把 List[Future] 轉為 Future[List]。
2)忽略 STTP Response 里除去 body 數據的其它部分,并把 response 轉為 Either[Throwable, NasaData]。
3)經過步驟 1,2,數據類型已經是 Future[List[Either[Throwable, NasaData]]]。
4)List[Either[Throwable, NasaData]] 轉為 (List[Throwable], List[NasaData])的思路是:
a) 構造一個空的 Tuple (List[Throwable(), List[NasaData]())作為一個累計器。
b) 使用 List.folderLeft()遍歷元素,根據是 left 還是 right 累加到累計器的_1 或_2。
下面鏈接的文章演示了兩種轉換方式,一種是 Scala 原生手寫,一種是使用 CAT。
但是,其中語句 case Left(err) => acc.left.map(_ => err) 的邏輯似乎與期望不符。如果 list of either 中有 Left,并不能工作。
val erA: Either[String, Int] = Right(1) val erB: Either[String, Int] = Right(2) val erC: Either[String, Int] = Right(3) val elA: Either[String, Int] = Left("error1") val elB: Either[String, Int] = Left("error2") val listOfEither = List(erA, elA, erB, erC, elB) private val eitherOfList: Either[String, List[Int]] = listOfEither.foldLeft(Right[String, List[Int]](List()).asInstanceOf[Either[String, List[Int]]])((acc, elem) => { elem match { case Right(v) => acc.map(l => l :+ v) case Left(e) => acc.left.map(_ + e) } }) println(s"eitherOfList: $eitherOfList")
輸出如下,并沒有error部分的信息。
eitherOfList: Right(List(1, 2, 3))
下面的代碼演示了并發發出100個RestAPi請求獲取數據的處理代碼,結果保存在Tuple里,分別是所有失敗和成功的數據。
import io.circe.generic.auto._
import sttp.client._
import sttp.client.akkahttp.AkkaHttpBackend
import sttp.client.circe._
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
val NASA_API_KEY = "XXXXXXXXXXXXXXX"
val baseUrl = s"https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=${NASA_API_KEY}"
var pageSize = 10
var pageNumb = 100
case class Links(self: String, next: String)
case class Page(number: Int, size: Int, total_elements: Int, total_pages: Int)
case class NearEarthObject(absolute_magnitude_h: Double, designation: String)
case class NasaData(links: Links, page: Page, near_earth_objects: List[NearEarthObject])
implicit val sttpBackend = AkkaHttpBackend()
val listOfFutureResult: List[Future[Response[Either[ResponseError[io.circe.Error], NasaData]]]] =
(0 until pageNumb).toList.map(pageIndex => {
val pageUrl = s"http://www.neowsapp.com/rest/v1/neo/browse?page=$pageIndex&size=$pageSize&api_key=${NASA_API_KEY}"
basicRequest.get(uri"$pageUrl")
.response(asJson[NasaData])
.send()
})
// Note: Future[List] --> List[Future]
val futureOfList: Future[List[Response[Either[ResponseError[io.circe.Error], NasaData]]]] = Future.sequence(listOfFutureResult)
// Note: 把Response[Either[ResponseError[io.circe.Error], NasaData]] 轉為了 Either[Throwable, NasaData]
val respOfEither2Either: Response[Either[ResponseError[io.circe.Error], NasaData]] => Either[Throwable, NasaData] = resp => {
println(s"resp==> code:${resp.code.code} ${resp.statusText}")
val newEither: Either[Throwable, NasaData] = resp.body match {
case Left(respErr) => Left(respErr.getCause)
case Right(nasaData) => Right(nasaData)
}
newEither
}
val futureOfListOfEither: Future[List[Either[Throwable, NasaData]]] = futureOfList.map(listOfResp => {
listOfResp.map(respOfEither2Either)
})
val listOfEither2TupleOfList: List[Either[Throwable, NasaData]] => (List[Throwable], List[NasaData]) = listE => {
listE.foldLeft(List[Throwable](), List[NasaData]())((acc, eData) => {
eData match {
case Right(nasaData) => (acc._1, acc._2 :+ nasaData)
case Left(t) => (acc._1 :+ t, acc._2)
}
})
}
val futureOfTupleOfList = futureOfListOfEither map listOfEither2TupleOfList
val result = Await.result(futureOfTupleOfList, 1.minute)
println(s"Exceptions in Response: $result._1")
println(s"Data in Response: $result._2")
另,Akka HTTP默認主機連接數是32個,所以需要修改applicaiton.confg配置以支持更多連接數。
akka.http.host-connection-pool.max-open-requests = 128
“STTP的基本使用方法是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。