Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to dispose of a disposable within an observable

Tags:

swift

rx-swift

I have an HTTPService which returns an Observable<NSData>. My goal is to compose that service into another service, ServiceA which transforms that data for my use case. Using Observable.create in RxSwift 2.0.0-rc.0 in ServiceA it's straight forward enough. My question is how to properly handle the disposable returned from the subscription of the HTTPService.

If I don't do anything I get the compile time warning that the result of call is unused: http://git.io/rxs.ud. I understand from reading that if I do nothing it's likely ok: (where xs mentioned below is let xs: Observable<E> ....

In case xs terminates in a predictable way with Completed or Error message, not handling subscription Disposable won't leak any resources, but it's still preferred way because in that way element computation is terminated at predictable moment.

So here is how I am currently addressing it, and also where I am wondering if I am doing this properly or if I have misunderstood something.

public struct ServiceA{

    public static func changes() -> Observable<ChangeSet>{
        return Observable.create{ observable in

            // return's Observable<NSData>
            let request = HTTPService.get("https://httpbin.org/get")

            let disposable = request.subscribe(
                onNext: { data in
                    // Do more work to transform this data
                    // into something meaningful for the application.
                    // For example purposes just use an empty object
                    observable.onNext(ChangeSet())
                    observable.onCompleted()
                },

                onError:{ error in
                    observable.onError(error)
                })

            // Is this the right way to deal with the
            // disposable from the subscription in this situation?
            return AnonymousDisposable{
                disposable.dispose()
            }
        }
    }
}
like image 273
AJ Venturella Avatar asked Dec 31 '15 15:12

AJ Venturella


1 Answers

As documentation says

subscribe function returns a subscription Disposable that can be used to cancel computation and free resources.
Preferred way of terminating these fluent calls is by using .addDisposableTo(disposeBag) or in some equivalent way. When disposeBag gets deallocated, subscription will be automatically disposed.

Actually your example looks fine in terms of rules, but it loos pretty bad ;) (Also it would be ok, if you would just return this disposable) :

public static func changes() -> Observable<ChangeSet>{
        return Observable.create{ observable in

            // return's Observable<NSData>
            let request = HTTPService.get("https://httpbin.org/get")

            return request.subscribe(
                onNext: { data in
                    // Do more work to transform this data
                    // into something meaningful for the application.
                    // For example purposes just use an empty object
                    observable.onNext(ChangeSet())
                    observable.onCompleted()
                },

                onError:{ error in
                    observable.onError(error)
                    })
}

But as you you returning Observeble I wonder, why you dont just use map operator ?

In your example it would be something like this:

public static func changes() -> Observable<ChangeSet> {
    return HTTPService.get("https://httpbin.org/get")
                      .map(ChangeSet.init)
}
like image 54
Serg Dort Avatar answered Oct 04 '22 18:10

Serg Dort