1. assertNotFailure

public enum SubjectError : Error {
    case genericSubjectError
}

let subject = CurrentValueSubject<String,Error>("initial value")

subject
    .assertNoFailure()
    .sink(receiveCompletion: {print("completion \\($0)")}, receiveValue: {print("value \\($0)")})
subject.send("second value")
subject.send(completion: Subscribers.Completion<Error>.failure(SubjectError.genericSubjectError))

/**
value initial value
value second value
*/

2. Catch

let stream = numbers.publisher
    .tryLast {
        print($0)
        guard $0 != 0 else { throw SimpleError()}
        return true
    }
    .catch({ error in
        Just(-1)
    })
        .sink(receiveValue: {print("value \\($0)")})
        .store(in: &cancellables)
//print -1

3. tryCatch

업스트림의 오류를 다른 퍼블리셔로 바꾸거나 새 오류를 발생시켜줌

enum SimpleError: Error { case error }
var numbers = [5, 4, 3, 2, 1, -1, 7, 8, 9, 10]

cancellable = numbers.publisher
   .tryMap { v in
        if v > 0 {
            return v
        } else {
            throw SimpleError.error
        }
}
  .tryCatch { error in
      Just(0) // Send a final value before completing normally.
              // Alternatively, throw a new error to terminate the stream.
}
  .sink(receiveCompletion: { print ("Completion: \\($0).") },
        receiveValue: { print ("Received \\($0).") }
  )
//    Received 5.
//    Received 4.
//    Received 3.
//    Received 2.
//    Received 1.
//    Received 0.
//    Completion: finished.
enum SimpleError : Error {
    case testError
}
var numbers = [5,4,3,2,1,-1,7,8,9,10]
let cancellable = numbers.publisher
    .tryMap { v in
        if v>0{
            return v
        }else{
            throw SimpleError.testError
        }
    }
    .tryCatch { error -> AnyPublisher<Int,SimpleError> in
        throw SimpleError.testError
    }
    .sink(receiveCompletion: {print("completion: \\($0)")}, receiveValue: {print("value = \\($0)")})

/**
Received 5.
Received 4.
Received 3.
Received 2.
Received 1.
Completion: failure(__lldb_expr_3.SimpleError.error).
*/

Retry

struct WebSiteData: Codable {
    var rawHTML: String
}

let myURL = URL(string: "<https://www.example.com2>")

let cancellable = URLSession.shared.dataTaskPublisher(for: myURL!)
    .print()
    .retry(3)
    .map({ (page) -> WebSiteData in
        return WebSiteData(rawHTML: String(decoding: page.data, as: UTF8.self))
    })
    .catch { error in
        return Just(WebSiteData(rawHTML: "<HTML>Unable to load page - timed out.</HTML>"))
}
.sink(receiveCompletion: { print ("completion: \\($0)") },
      receiveValue: { print ("value: \\($0)") }
 )

예시추가

struct ParseError: Error{
}

func romanNumeral(from:Int) throws -> String{
    let romanNumeralDict : [Int: String] = [1:"I", 2:"II", 3:"III", 4:"IV", 5:"V"]
    guard let numeral = romanNumeralDict[from] else{
        throw ParseError()
    }
    return numeral
}

let numbers = [1,2,3,0]
let cancellable = numbers.publisher
    .tryMap{ try romanNumeral(from: $0)}
    .retry(2)
    .sink(
           receiveCompletion: { print ("completion: \\($0)") },
           receiveValue: { print ("\\($0)", terminator: " ") }
        )
/*
I II III I II III I II III completion: failure(__lldb_expr_11.ParseError())
2번 리트라이후 에러를 방출함.
*/