【问题标题】:Chained Throwing Futures in SwiftNIO & VaporSwiftNIO 和 Vapor 中的链式投掷期货
【发布时间】:2020-06-19 18:57:07
【问题描述】:

在 Vapor 4 中,我通过在 3rd 方 API 上调用请求并根据我返回的结果返回一个值来处理发布请求。以下代码导致错误:“从抛出函数...到非抛出函数的无效转换”

 app.post("activate") { req -> EventLoopFuture<ActivationRequestResponse> in

        return req.client.post("https://api.example.com/activation", headers: HTTPHeaders(), beforeSend: { (req) in
            try req.content.encode(RequestBody(value: someValue), as: .json)
        })

        .map { (response) -> ActivationRequestResponse in

            let response = try response.content.decode(ResponseModel.self)
            return ActivationRequestResponse(success: true, message: "success")

        }

    }

在获得 API 结果后,我似乎无法在链接的 map() 中使用 try。如果我在地图内的let response = try response.content.decode(ResponseModel.self) 中的try 中添加!,上面的代码将起作用,但理想情况下我想捕获这个错误。创建响应正文时使用的第一个 try 似乎隐式传递回链,但不是第二个。

我做错了什么?解码响应内容时如何捕获错误?为什么第一个 try 被抓到了,第二个没有被抓到?

【问题讨论】:

    标签: swift xcode vapor swift5.2 swift-nio


    【解决方案1】:

    map 的属性是它只会转换“成功路径”上的值。然而,您的转型可能会失败,这意味着您可能希望未来也失败。

    当您想使用成功或失败的函数转换值时,您需要使用flatMap* 函数之一。

    在您的情况下,尝试将map 替换为flatMapThrowing,然后它应该可以工作。

    【讨论】:

    • 看起来 flatMapThrowing 只能用于返回非未来。假设我需要通过另一个网络调用返回未来。有没有办法转换一个成功或失败的值,然后返回一个未来?
    【解决方案2】:

    要扩展 Johannes Weiss 的答案,要有一个返回未来的抛出闭包,您需要类似:

    future.flatMap {
        do {
            return try liveDangerously()
        } catch {
            future.eventLoop.makeFailedFuture(error)
        }
    }
    

    在这样做了太多次之后,我决定自己推出(虽然名字有点可疑):

    extension EventLoopFuture {
        @inlinable
        public func flatterMapThrowing<NewValue>(file: StaticString = #file,
                line: UInt = #line,
                _ callback: @escaping (Value) throws -> EventLoopFuture<NewValue>) -> EventLoopFuture<NewValue> {
            return self.flatMap(file: file, line: line) { (value: Value) -> EventLoopFuture<NewValue> in
                do {
                    return try callback(value)
                } catch {
                    return self.eventLoop.makeFailedFuture(error)
                }
            }
        }
    }
    

    这样你就可以写了:

    future.flatterMapThrowing {
        return try liveDangerously()
    }
    

    【讨论】:

      猜你喜欢
      • 2022-12-18
      • 1970-01-01
      • 2022-08-06
      • 1970-01-01
      • 2017-10-12
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多