You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala如何将基于val的响应处理重构为for-yield结构?

重构ZIO GET请求为Scala for-yield结构

原有实现代码

case Method.GET -> !! / "leagues" =>
  val openDotaResponse: ZIO[Client, Throwable, Response] = Client.request("https://api.opendota.com/api/leagues")
  val bodyOfResponse: ZIO[Client, Throwable, String] = openDotaResponse.flatMap(_.body.asString)
  val eitherListOfLeagues: ZIO[Client, Throwable, Either[String, List[League]]] = bodyOfResponse.map(_.fromJson[List[League]])
  val listOfLeagues: ZIO[Client, Throwable, List[League]] = eitherListOfLeagues.map(eitherList => eitherList.toOption.getOrElse(Nil))
  val result: ZIO[Client, Throwable, Response] = listOfLeagues.map(listLeagues => Response.json(listLeagues.toJson))
  result

正确的for-yield重构实现

case Method.GET -> !! / "leagues" =>
  for {
    // 发起请求,获取原始响应实例
    openDotaRes <- Client.request("https://api.opendota.com/api/leagues")
    // 提取响应体字符串(body.asString返回ZIO,用<-提取内部值)
    bodyStr <- openDotaRes.body.asString
    // 同步解析JSON为Either类型,纯逻辑直接赋值
    eitherLeagues = bodyStr.fromJson[List[League]]
    // 解析失败时返回空列表,成功则取解析结果
    leagues = eitherLeagues.toOption.getOrElse(Nil)
    // 构造最终要返回的Response对象
    response = Response.json(leagues.toJson)
  } yield response

重构时的关键注意点

你尝试的代码存在几个核心错误:

  • for推导式中<-左侧的变量是ZIO内部的具体值,不是ZIO类型,不需要标注ZIO[Client, Throwable, ...]
  • 纯同步操作(如JSON解析、Either转List)不需要包裹成ZIO,直接用val赋值即可
  • 无需手动嵌套flatMap/map,for推导式会自动处理ZIO的链式调用逻辑

内容的提问来源于stack exchange,提问作者BlackFriday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:40:52