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
相关产品推荐
相关产品推荐

