I don't know how to deal with errors in a Combine flow. I would like to be able to catch errors from a Combine function.
Could anyone help in explaining what I'm doing wrong here and how I should handle catching an error with Combine?
Note: The function below is just an example to illustrate a case where an error could be caught instead of crashing the app.
func dataFromURL<T: Decodable>(_ url: String, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<T, Error> {
// 1) Example: If the URL is not well-formatted, I would like to /create/raise/return an error (in a Combine way)
// 2) Instead of the forced unwrapping here, I would also prefer to raise a catchable error if the creation of the request fails
let request = URLRequest(url: URL(string:url)!)
// 3) Any kind of example dealing with potential errors, etc
return urlSession
.dataTaskPublisher(for: request)
.tryMap { result -> T in
return try decoder.decode(T.self, from: result.data)
}
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
// function in another file:
func result() {
// I would like to be able to catch or handle errors in this function
dataFromURL("test").print()
// Example : if error 1), else if error 2) etc
}
As explained in the comments, I would like to be able to catch any error outside the dataFromURL function, but in a "Combine way".
I used a URL data fetching as an example, but it could be with anything else.
What is the recommended way to raise and catch errors with the Combine flow? Is it to return a Publisher with a specific error for example? If so, how can I do it?
EDIT
Without Combine, I would just have thrown an error, added the throws keyword to the function, and would have caught the error in the result function.
But I would have expected Combine to have a simpler or more elegant way to achieve this. For example, maybe something that can be thrown at any time:
guard <url is valid> else {
return PublisherError(URLError.urlNotValid)
}
And could have been caught like this:
dataFromURL
.print()
.onError { error in
// handle error here
}
.sink { result in
// no error
}