Combine: AnyPublisher<Response, Error> to AnyPublisher<Response, Never>

Viewed 1131

I have a particular situation where the returning function provides something like AnyPublisher<Response, Error>. But from the calling function, I want to return AnyPublisher<Response, Never>.

//just an example
func getList(_ request: QueryRequest) -> AnyPublisher<Response, Never> {
   return executeQuery(request).eraseToAnyPublisher()
}

func executeQuery(_ request: QueryRequest) -> AnyPublisher<Response, Error> {
   return someData().eraseToAnyPublisher()
}

When I do this, I am getting Cannot convert return expression of type 'AnyPublisher<Response, Error>' to return type 'AnyPublisher<Response, Never>'

How do I do convert to AnyPublisher<Response, Never> without modifying the called function?

Note: I cannot modify the called function's return type as it's used by other methods which make use of Error

1 Answers

To convert from an upstream publisher that can fail to one that never fails, you need to decide how to handle a case when an error does occur (since it cannot be sent to your downstream).

If you "know" that it will never occur in your specific case, you can assert that there won't be an error:

return executeQuery(request)
          .assertNoFailure("this shouldn't have happened")
          .eraseToAnyPublisher()

Or you can just ignore it (by catching and replacing it with an Empty publisher) , which would complete your pipeline:

return executeQuery(request)
          .catch { _ in Empty<Response, Never>() }
          .eraseToAnyPublisher()

You can also replace an error with some value with .replaceError(with:)

Note, that when there is an error from executeQuery publisher (the upstream), it completes the pipeline, so your downstream will receive a completion as well.

You can't continue to receive values from an errored-out upstream, as you asked about in comments. You might consider re-subscribing with .retry if you believe the error was transient (e.g. server is unreachable)

Related