簡體   English   中英

IO.async 回調問題與cats.effect 在Scala

[英]IO.async callback problem with cats.effect in Scala

我試圖通過 Scala 中的 java11 HttpClient重寫 httpclient

這是我的代碼:

import cats.effect._
import java.net.http._
import java.net.http.HttpResponse._
import java.net.http.HttpClient._

trait HttpClients[F[_]] {
  def send(req: HttpRequest)(implicit F: Async[F]): F[HttpResponse[_]]
}

object HttpClients {
  val client: HttpClient = HttpClient.newBuilder().followRedirects(Redirect.ALWAYS).build()
  def newClient[F[_] : Async](): HttpClients[F] = new HttpClients[F] {
    override def send(req: HttpRequest)(implicit F: Async[F]): F[HttpResponse[_]] = F.async { cb =>
      val resp = client.sendAsync(req, BodyHandlers.ofString())
      val s = resp.handle((res: HttpResponse[String], err: Throwable) => {
        if (err == null)
          cb(Right(res))
        else
          cb(Left(err))
      })
      s // TODO ?
      // Type missmatch
      // Required: F[Option[F[Unit]]]
      // Found:    Unit
    }
  }
}

來自this的句柄回調

我猜錯誤來自這里,但我不知道接下來該怎么寫。

然后我做了一些改變:

  def newClient[F[_] : Async](): HttpClients[F] = new HttpClients[F] {
    override def send(req: HttpRequest)(implicit F: Async[F]): F[HttpResponse[_]] = F.async[HttpResponse[_]] { cb =>
      val s = Sync[F](F: Async[F]).delay {
        val resp = client.sendAsync(req, BodyHandlers.ofString())
        resp.handle((res: HttpResponse[String], err: Throwable) => {
          if (err == null)
            cb(Right(res))
          else
            cb(Left(err))
        }).join()
      }
      F.delay(s.some)
    }
  }

這一次,沒有錯誤,但我不知道如何獲取響應的正文

感謝您的回復!

@OlegPyzhcov 已經在您使用CE3的情況下提供了見解,這個答案是使用CE2以防您想要什么。

代碼的第一個版本是正確的,這是一個使用Ammonite並進行了一些樣式改進並確保為每次調用和評估newClient創建一個新客戶端的完整運行示例

// scala 2.13.5

import $ivy.`org.typelevel::cats-effect:2.5.0`

import cats.effect.{Async, IO}
import cats.syntax.all._
import java.net.URI
import java.net.http.{HttpClient, HttpRequest, HttpResponse}

trait HttpClients[F[_]] {
  def send(req: HttpRequest): F[HttpResponse[String]]
}

object HttpClients {
  def newClient[F[_]](implicit F: Async[F]): F[HttpClients[F]] =
    F.delay {
      HttpClient
        .newBuilder
        .followRedirects(HttpClient.Redirect.ALWAYS)
        .build()
    } map { client =>
      new HttpClients[F] {
        override def send(req: HttpRequest): F[HttpResponse[String]] =
          F.async { cb =>
            client.sendAsync(req, HttpResponse.BodyHandlers.ofString).handle {
              (res: HttpResponse[String], err: Throwable) =>
                if (err == null) cb(Right(res))
                else cb(Left(err))
            }
          }
      }
    }
}

object Main {
  private val request =
    HttpRequest
      .newBuilder
      .GET
      .uri(URI.create("https://stackoverflow.com/questions/tagged/scala?tab=Newest"))
      .build()

  private val program = for {
    _ <- IO.delay(println("Hello, World!"))
    client <- HttpClients.newClient[IO]
    response <- client.send(request)
    _ <- IO.delay(println(response))
    _ <- IO.delay(println(response.body))
  } yield ()

  def run(): Unit = {
    program.unsafeRunSync()
  }
}

@main
def main(): Unit = {
  Main.run()
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM