Nick
Nick

Reputation: 3435

Best practice to cancel subscription as soon as another subscription fires

I have two subscriptions: a and b. As soon as b "fires", I need to cancel (unsubscribe) a.

The subscriptions are defined in different parts of the code and currently it looks like this:

private let _bag = DisposeBag()

func fA() {
    // ....

    observableA.bind(to: mapView.rx.animate).disposed(by: _bag)

    // ....
}

func fB() {
    // ....

    observableB.subscribe(onNext: { [unowned self] data in
        self.process(data)
        // I need to unsubscribe from observableA now 
    }).disposed(by: _bag)

    // ....
}

What would be a best way to accomplish it? I can think of two ways:

1) Use special bag:

private let _bag = DisposeBag()
private var _ABAG = DisposeBag()

func fA() {
    // ....

    observableA.bind(to: mapView.rx.animate).disposed(by: _ABAG)

    // ....
}

func fB() {
    // ....

    observableB.subscribe(onNext: { [unowned self] data in
        self.process(data)
        self._ABAG = DisposeBag()
    }).disposed(by: _bag)

    // ....
}

2) Manually unsubscribe:

private let _bag = DisposeBag()
private var _disposableA: Disposable?

func fA() {
    // ....

    _disposableA = observableA.bind(to: mapView.rx.animate)

    // ....
}

func fB() {
    // ....

    observableB.subscribe(onNext: { [unowned self] data in
        self.process(data)
        self._disposableA?.dispose()
    }).disposed(by: _bag)

    // ....
}

Which way is better in terms of robustness, elegancy, etc.? Or is there better way?

Upvotes: 0

Views: 42

Answers (1)

Manuel Aurora
Manuel Aurora

Reputation: 46

Can you use a "takeUntil" operator? You can receive elements from observableA until observableB fires, like you wanted.

My test:

 2019-12-30 19:18:32.016: A SUB -> Event next(())
 2019-12-30 19:18:47.017: A SUB -> isDisposed
 2019-12-30 19:18:47.018: B SUB -> Event next(())


observableA
        .debug("A SUB", trimOutput: false)
        .takeUntil(observableB)

Upvotes: 3

Related Questions