繁体   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