简体   繁体   中英

Swift Combine: How to specify the Error type of tryMap(_:)?

In the Combine framework, we can throw a generic Error protocol type while using tryMap .

However, how can we be more specific about the Error type?

For example,

let publisher = urlSession.dataTaskPublisher(for: request).tryMap { (data, response) -> (Data, HTTPURLResponse) in
      guard let response = response as? HTTPURLResponse else {
        throw URLError(.cannotParseResponse)
      }
      return (data, response)
}

How to specify the Error type of this publisher ? I'd like to use URLError instead of Error .

I found the method setFailureType(to:) in the Combine framework. However, it is not available to tryMap(_:) .

setFailureType(to:) is only to force the failure type of a publisher with failure type Never . tryMap always uses Error as the error type because any Error could be thrown in the closure body, so you need to use mapError to force the URLError type:

let map_error = publisher.mapError({ error -> URLError in
    switch (error) {
    case let url_error as URLError:
        return url_error
    default:
        return URLError(.unknown)
    }
})

You can also accomplish this with flatMap . This will allow you to specify both the Output and Error type at once, like so:

struct SomeResponseType {
    let data: Data
    let response: HTTPURLResponse
}

let publisher = urlSession.dataTaskPublisher(for: request)
    .flatMap { (data, response) -> AnyPublisher<SomeResponseType, URLError > in
      guard let response = response as? HTTPURLResponse else {
        return Fail(error: URLError(.cannotParseResponse))
            .eraseToAnyPublisher()
      }
      return Just(SomeResponseType(data: data, response: response)
          .setFailureType(to: URLError)
          .eraseToAnyPublisher()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM