首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ZLayer类型不匹配的Sttp客户端3

ZLayer类型不匹配的Sttp客户端3
EN

Stack Overflow用户
提问于 2021-05-07 21:08:04
回答 1查看 104关注 0票数 1

我使用ZLayer和Sttp Client(异步)来创建简单的http请求者应用程序,但我发现类型不匹配错误,我不能解决它。有人能告诉我为什么会出现类型不匹配错误吗?

我使用这些版本的scala和库。

java -> 8.282.08.1-amzn

scala -> s.13.5

dev.zio -> 1.0.7

com.softwaremill.sttp.client3 -> 3.3.0

代码语言:javascript
复制
type mismatch;
 found   : zio.ZLayer[sttp.client3.asynchttpclient.zio.SttpClient,Nothing,ZlayerAndSttp.HttpBin]
    (which expands to)  zio.ZLayer[zio.Has[sttp.client3.SttpBackend[zio.Task,sttp.capabilities.zio.ZioStreams with sttp.capabilities.WebSockets]],Nothing,zio.Has[ZlayerAndSttp.HttpBin.Service]]
 required: zio.ZLayer[ZlayerAndSttp.HttpBin,?,?]
    (which expands to)  zio.ZLayer[zio.Has[ZlayerAndSttp.HttpBin.Service],?,?]
    program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live)

下面是完整的代码

代码语言:javascript
复制
import zio._
import sttp.client3._
import sttp.client3.circe._
import sttp.client3.asynchttpclient.zio._
import io.circe.generic.auto._
import zio.console.Console


object ZlayerAndSttp extends App {

  case class HttpBinResponse(origin: String, headers: Map[String, String])

  type HttpBin = Has[HttpBin.Service]
  object HttpBin {
    trait Service {
      def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse]
    }

    val live: ZLayer[SttpClient, Nothing, HttpBin] = ZLayer.succeed(new Service {
      override def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = {
        val request = basicRequest
          .get(uri"https://httpbin.org/get")
          .response(asJson[HttpBinResponse])
        sendR(request).map(_.body).absolve.map(res => HttpBinResponse(res.origin, res.headers))
      }
    })

    def sendRequest: ZIO[HttpBin with SttpClient, Throwable, HttpBinResponse] = ZIO.accessM(_.get.sendRequest)
  }

  val request = basicRequest
    .get(uri"https://httpbin.org/get")
    .response(asJson[HttpBinResponse])

  override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
    val program = for {
      result <- HttpBin.sendRequest
      _ <- console.putStrLn(s"${result.origin}, ${result.headers}")
    } yield ()
    program.provideCustomLayer((AsyncHttpClientZioBackend.layer() >>> HttpBin.live) >>> HttpBin.live) // type mismatch
      .exitCode

    // ↓these lines of code run with no errors but I can't understand why
//    val program: ZIO[Console with SttpClient, Throwable, Unit] = for {
//      response <- send(request)
//      _ <- console.putStrLn(s"${response.body.toString}")
//    } yield ()
//    program.provideCustomLayer(AsyncHttpClientZioBackend.layer()).exitCode
  }

}
EN

回答 1

Stack Overflow用户

发布于 2021-05-09 21:16:20

你似乎让你的生活变得有点复杂。

最终代码是什么样子取决于您想要在这里实现什么。如果您试图在HttpBin接口后面隐藏Sttp的使用,那么您的层定义应该如下所示:

代码语言:javascript
复制
    val live: ZLayer[SttpClient, Nothing, HttpBin] = 
      (for {
        client <- ZIO.environment[SttpClient]
      } yield new Service {
          override def sendRequest: ZIO[Any, Throwable, HttpBinResponse] = {
            val request = basicRequest
              .get(uri"https://httpbin.org/get")
              .response(asJson[HttpBinResponse])

            sendR(request)
              .map(_.body)
              .absolve
              .map(res => HttpBinResponse(res.origin, res.headers))
              .provide(client)
  }
      }).toLayer

那么你的存取器方法变成:

代码语言:javascript
复制
def sendRequest: ZIO[HttpBin, Throwable, HttpBinResponse] = 
  ZIO.accessM(_.get.sendRequest)

您可以通过以下方式使用它:

代码语言:javascript
复制
  override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = {
    val program = for {
      result <- HttpBin.sendRequest
      _ <- console.putStrLn(s"${result.origin}, ${result.headers}")
    } yield ()

    program
      .provideCustomLayer(AsyncHttpClientZioBackend.layer() >>> HttpBin.live)
      .exitCode

这里要注意的是,对于层组合,我只使用垂直运算符,因为HttpBin.live依赖于带有SttpClient的层,但我们对调用方法“隐藏”了这一事实,以便您可以在需要时创建不需要Sttp的HttpBintest变体。

如果您不需要信息隐藏,您可以完全删除中间层,并将您的sendRequest视为独立的方法。

代码语言:javascript
复制
object HttpBin {
  def sendRequest: ZIO[SttpClient, Throwable, HttpBinResponse] = {
     val request = basicRequest
       .get(uri"https://httpbin.org/get")
       .response(asJson[HttpBinResponse])

     sendR(request)
       .map(_.body)
       .absolve
       .map(res => HttpBinResponse(res.origin, res.headers))
}

然后,您只需调用此方法,所需做的就是提供SttpClient层。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67435567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档