2

I have a getDimensions method which returns an Observable<string[]>.

dimension.service.ts

public getDimensions(id: string): Observable<string[]> {
    return this.service.loadDimensions(id);
}

reloader.service.ts

public update(idsToUpdate: string[]): void {

    idsToUpdate.map(id => this.dimensionService.getDimensions(id)).pipe(
        map(
             newDimensions => this.updateDimensions(newDimensions)
        )
    ).subscribe(); // ToDo: unsubscribe

}

Then in another part of the app, I'm calling this method inside update method. The problem is, I don't know how to properly unsubscribe from getDimensions. One possibly solution can be, to create a Subscription and then in OnDestroy call unsubscribe, but for me it's not good solution:

  • this is a service, which I'm using in my entire application, so the OnDestroy hook will never occur
  • I'm calling the update method every n seconds, so there will be every n seconds a new subscription

Possible solution: (Not good)

reloader.service.ts

private subscriptions: Subscription = new Subscription();

...
...

public update(idsToUpdate: string[]): void {

    const sub = idsToUpdate.map(id => this.dimensionService.getDimensions(id)).pipe(
        map(
             newDimensions => this.updateDimensions(newDimensions)
        )
    ).subscribe(); // ToDo: unsubscribe

    this.subscription.add(sub);

}

...
...

public onDestroy(): void {
    this.subscription.unsubscribe();
}

EDIT:

As @jgerstle mentioned in his comment, if the observable completes (which is my case), there is no need to unsubscribe.

Runtime Terror
  • 6,242
  • 11
  • 50
  • 90
  • 1
    possible duplicate https://stackoverflow.com/q/40861494/7812112 – Sarthak Aggarwal Nov 02 '18 at 06:51
  • 1
    I'm not 100% sure why you want to unsubscribe, is it because you only want the first return? If so you can just use the first operator: http://reactivex.io/documentation/operators/first.html which will automatically unsubscribe after the first item returns. Also if the observable completes it will automatically unsubscribe, if I'm not mistaken. You can also unsubscribe in the subscribe if you need to, or maybe add a finally clause. Again I'm not really sure why you want to unsubscribe. – jgerstle Nov 02 '18 at 07:14
  • @jgerstle, yes I just now realized that it completes and after that it's "unsubscribed" already. – Runtime Terror Nov 02 '18 at 07:37
  • @Gabriel So then what's the issue? I guess my real question is when do you want to unsubscribe? – jgerstle Nov 02 '18 at 07:42
  • @jgerstle, there is no issue now. As I sad, I just after your comment realized those things. So the answer to my question is, that I don't need to unsubscribe in this case. – Runtime Terror Nov 02 '18 at 07:49
  • ah ok got it glad I could help :) – jgerstle Nov 02 '18 at 07:55

2 Answers2

0

If you want to unsubscribe when you got the data or observable complete

public update(idsToUpdate: string[]): void {

    const sub = idsToUpdate.map(id => this.dimensionService.getDimensions(id)).pipe(
        map(
             newDimensions => this.updateDimensions(newDimensions)
        )
    ).subscribe(() => sub.unsubscribe() ); // or you can use complate 

}
Muhammed Albarmavi
  • 23,240
  • 8
  • 66
  • 91
0

The add function of subscriptions might not do what you are trying to do. From the documentation is states the following.

   /**
     * Adds a tear down to be called during the unsubscribe() of this
     * Subscription.
     *
     * If the tear down being added is a subscription that is already
     * unsubscribed, is the same reference `add` is being called on, or is
     * `Subscription.EMPTY`, it will not be added.
     *
     * If this subscription is already in an `closed` state, the passed
     * tear down logic will be executed immediately.
     *
     * @param {TeardownLogic} teardown The additional logic to execute on
     * teardown.
     * @return {Subscription} Returns the Subscription used or created to be
     * added to the inner subscriptions list. This Subscription can be used with
     * `remove()` to remove the passed teardown logic from the inner subscriptions
     * list.
     */
    add(teardown: TeardownLogic): Subscription;

I guess what you want to do is unsubscribe from your idsToUpdate-subscription. You can do that by keeping the reference of the subscription as you do, and do a sub.unsubscribe()

Here is an example by modifing your code

private sub: Subscription;

...
...

public update(idsToUpdate: string[]): void {

    this.sub = idsToUpdate.map(id => this.dimensionService.getDimensions(id)).pipe(
        map(
             newDimensions => this.updateDimensions(newDimensions)
        )
    ).subscribe(); // ToDo: unsubscribe

}

...
...

public onDestroy(): void {
    if(this.sub) this.sub.unsubscribe();

}
John
  • 10,165
  • 5
  • 55
  • 71