Home Rxswift Operator Catch
Post
Cancel

Rxswift Operator Catch

Catch

Continues an observable sequence that is terminated by an error with the observable sequence produced by the handler.

1
2
3
4
public func catchError(_ handler: @escaping (Swift.Error) throws -> Observable<Element>)
    -> Observable<Element> {
    return Catch(source: self.asObservable(), handler: handler)
}

Continues an observable sequence that is terminated by an error with a single element.

1
2
3
4
public func catchErrorJustReturn(_ element: Element)
    -> Observable<Element> {
    return Catch(source: self.asObservable(), handler: { _ in Observable.just(element) })
}

final private class CatchSinkProxy<Observer: ObserverType>: ObserverType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typealias Element = Observer.Element
typealias Parent = CatchSink<Observer>

private let _parent: Parent

func on(_ event: Event<Element>) {
    self._parent.forwardOn(event)

    switch event {
    case .next:
        break
    case .error, .completed:
        self._parent.dispose()
    }
}

final private class CatchSink<Observer: ObserverType>: Sink, ObserverType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
typealias Element = Observer.Element 
typealias Parent = Catch<Element>

private let _parent: Parent
private let _subscription = SerialDisposable()

func run() -> Disposable {
    let d1 = SingleAssignmentDisposable()
    self._subscription.disposable = d1
    d1.setDisposable(self._parent._source.subscribe(self))

    return self._subscription
}

func on(_ event: Event<Element>) {
    switch event {
    case .next:
        self.forwardOn(event)
    case .completed:
        self.forwardOn(event)
        self.dispose()
    case .error(let error):
        do {
            let catchSequence = try self._parent._handler(error)

            let observer = CatchSinkProxy(parent: self)
// `subscribe` the handler returned observable on `error`
            self._subscription.disposable = catchSequence.subscribe(observer)
        }
        catch let e {
            self.forwardOn(.error(e))
            self.dispose()
        }
    }
}

final private class Catch: Producer

1
2
3
4
5
6
7
8
9
10
typealias Handler = (Swift.Error) throws -> Observable<Element>

fileprivate let _source: Observable<Element>
fileprivate let _handler: Handler

override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element {
    let sink = CatchSink(parent: self, observer: observer, cancel: cancel)
    let subscription = sink.run()
    return (sink: sink, subscription: subscription)
}
This post is licensed under CC BY 4.0 by the author.