Thomvis / BrightFutures

Write great asynchronous code in Swift using futures and promises
MIT License
1.9k stars 184 forks source link

No option to throw an error inside map #214

Closed RahavLussato closed 4 years ago

RahavLussato commented 4 years ago

I want to use map and in the map I have a function that can throw an error, in that case, I would like the new future to fail, when i try to do that i get an error "Invalid conversion from throwing function of type '() throws -> ' to non-throwing function type '(JSON) -> _'" is there an option to throw an error inside the map function ?

Screen Shot 2020-03-11 at 22 37 18
Thomvis commented 4 years ago

Hi @RahavLussato. BrightFutures uses typed errors and therefore doesn't directly work with Swift's untyped throws. The alternative is to use the flatMap variant that allows you to return a Result: https://github.com/Thomvis/BrightFutures/blob/master/Sources/BrightFutures/AsyncType+ResultType.swift#L72.

RahavLussato commented 4 years ago

Thanks @Thomvis , can you help me how should i write this ? i tried like this but its not compiling, "Cannot invoke 'flatMap' with an argument list of type '(@escaping (JSON) -> Result)'"

return client.call(method: method, params: json).flatMap { (json:JSON) -> Result<JSON> in
                var result: Result<JSON, Error>

                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = response
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = error
                }

                return result
            }
Thomvis commented 4 years ago

A couple of things:

RahavLussato commented 4 years ago

Thanks @Thomvis but still getting errors :(

  1. Cannot invoke 'flatMap' with an argument list of type '(@escaping (JSON) -> <>)'
  2. Generic type 'Result' specialized with too many type parameters (got 2, but expected 1)
return client.call(method: method, params: json).flatMap { (json:JSON) -> Result<JSON, Error> in
                var result: Result<JSON, Error>

                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = .success(response)
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = .failure(response)
                }

                return result
            }
RahavLussato commented 4 years ago

Screen Shot 2020-03-12 at 11 00 53

Thomvis commented 4 years ago

It seems like the compiler is confused about which Result type to use. Do you or any of your dependencies declare one with a single type parameter?

RahavLussato commented 4 years ago

nothing that I can find, can I specify it?

RahavLussato commented 4 years ago

now it compiled :)

return client.call(method: method, params: json).flatMap { (json:JSON) -> Swift.Result<T, Error> in
                var result: Swift.Result<T, Error>

                do {
                    let response = try self.decoder.decode(responseType, from: json.rawData())
                    DDLogDebug("call process \(json)")
                    result = .success(response)
                }
                catch let error {
                    DDLogError("Parse \(method) response failed: \(json) with error \(error.localizedDescription)")
                    result = .failure(error)
                }

                return result
            }
RahavLussato commented 4 years ago

@Thomvis so does it going to return to the right callback (onSuccess / onFailure) by the type of the result ?