2

在 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 结果后,我似乎无法try在我的链中使用。如果我在地图内部添加一个,map()上面的代码将起作用,但理想情况下我想捕捉这个错误。创建响应主体时使用的第一个似乎隐式传递回链,但不是第二个。!trylet response = try response.content.decode(ResponseModel.self)try

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

4

2 回答 2

3

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

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

在您的情况下,请尝试替换mapflatMapThrowing,然后它应该可以工作。

于 2020-03-07T06:21:36.893 回答
3

要扩展 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()
}
于 2020-05-19T15:39:37.507 回答