開始之前,先建立 Error 與 Function
enum DemoError: Error {case noReason}
func willThrow(_ nb:Int) throws -> String {
    throw DemoError.noReason
}
在不使用 Combine 的情形下,我們會這樣處理:
let result:String
do {
   result = try willThrow(1)
} catch {
    //handle Error
}
甚至有些時候會使用 try!/try? 來快速處理,而在套用 Combine 之後,我們可以用第 14 篇的失敗處理類型來處理
Just(1)
    .tryMap{ try willThrow($0)}
    .sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            fatalError()
        case .failure(let error):
            print(error)
        }
    }, receiveValue: {fatalError()})
要使用 Result 時,需要一個幫助的
extension Publisher {
    typealias PublisherResult = Result<Output,Failure>
    
    func mapToResult() -> AnyPublisher<Result<Self.Output, Self.Failure>, Never>{
        self.map{PublisherResult.success($0)}
            .catch{Just<PublisherResult>(.failure($0))}
            .eraseToAnyPublisher()
    }
}
如此一來,就將上游元素轉化為 Result 的 enum
Just(1)
    .tryMap{ try willThrow($0)}
    .mapToResult()
    .sink{ result in 
        switch result {
            case .success(let element): fatalError()
            case .failure(let error): print(error)
        }
    }
extension Publisher {
    func applyWhenFailure(receiveError: @escaping (Failure) -> Void) ->  Publishers.Catch<Self, Empty<Self.Output, Never>>{
       self.catch { error -> Empty<Output, Never> in
            receiveError(error)
            return Empty<Output,Never>()
        }
    }
}
以上是目前想到的錯誤處理方法。