Search code examples
swiftxcodevaporswift5swift-nio

Chained Throwing Futures in SwiftNIO & Vapor


In Vapor 4, I'm processing a post request by calling a request on a 3rd party API and returning a value based on the result I get back. The following code results in the error: "Invalid conversion from throwing function ... to non-throwing function"

 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")

        }

    }

I can't seem to use try in my chained map() after getting the API result. The above code will work if I add a ! to the try in let response = try response.content.decode(ResponseModel.self) inside the map, but ideally I want to catch this error. The first try used when creating the response body seems to be implicitly passed back up the chain, but not the second.

What am I doing wrong? How do I catch the error when decoding the response content? Why is the first try caught but not the second?


Solution

  • The property of map is that it will just transform a value on the “success path”. Your transformation may however fail which means that you presumably want the future to fail too.

    Whenever you want to transform a value with a function that either succeeds or fails you need to use one of the flatMap* functions.

    In your case, try replacing map with flatMapThrowing and then it should work.