Using a single subscription variable with BehaviorSubject

流过昼夜 提交于 2019-12-17 21:29:23

问题


I use BehaviorSubject in my Angular app and I get observable to my Details component from DataService as shown below:

DataService.ts:

export class DataService {

    private messageTracker = new BehaviorSubject<any>();
    private fileTracker = new BehaviorSubject<any>();

    getMessageTracker(): Observable<any> {
        return this.messageTracker.asObservable();
    }

    getFileTracker(): Observable<any> {
        return this.fileTracker.asObservable();
    }

    //set methods omitted for brevity
}


DetailComponent :

export class DetailComponent implements OnInit {

    subscription; //??? Can I use this variable for every subscription below?

    constructor(private dataService: DataService) { }

    ngOnInit(): void {

        this.subscription = this.dataService.getMessageTracker().subscribe((param: any) => {
                //...  
        });

        this.subscription = this.dataService.getFileTracker().subscribe((param: any) => {
            //...
        });
    }
}

ngOnDestroy(): void {
    this.subscription.unsubscribe();
}

My questions are:

1) As far as I know, as above, I should create a new BehaviorSubject variable for each event e.g. messageCreateTracker (for tracking a new message added), fileCreateTracker (for tracking a new file added, messageUpdateTracker (for tracking a message updated). Is that all true?

2) Looking DetailComponent, I just used a single subscription variable for every subscriptions of Observables. Is that a bad approach? Should I create a new subscription variable for each subscriptions in ngOnInit()?


回答1:


Answer For Query 1:

It depends on the developer's coding style, or how he thought, you can also pass the type of event and data with that, in that case, you will need only one BehaviorSubject, like this :

this.messageTracker.next({ type : 'create' ,  data });
this.messageTracker.next({ type : 'update' ,  data });
this.messageTracker.next({ type : 'delete' ,  data });

But this can also create a complexity if it goes large, gain depends on the requirements of the project, your way is also good.


Answer For Query 2:

Basically, you can't handle multiple subscriptions like that it will override the previous one and it will only unsubscribe the last one :

So you can create multiple variables for that OR single array/object of your subscription and then unsubscribe all :

With Array :

this.subscription = [];
this.subscription.push(this.dataService.getMessageTracker().subscribe((param: any) => {}));    
this.subscription.push(this.dataService.getFileTracker().subscribe((param: any) => {}));

ngOnDestroy(): void {
    this.subscription.forEach(sub => {
        sub.unsubscribe();
    })
}

With Object :

this.subscription = {};
this.subscription['messageTracker'] = this.dataService.getMessageTracker().subscribe((param: any) => {}));
this.subscription['fileTracker'] = this.dataService.getFileTracker().subscribe((param: any) => {}));

this.subscription['fileTracker'].unsubscribe(); // <--- You can also do
delete this.subscription['fileTracker']; // <--- then dont forgot to remove, or will throw error in ngOnDestroy

ngOnDestroy(): void {
    for(key in this.subscription) {
      this.subscription[key].unsubscribe();
    }
}



回答2:


though marked answer is well explained, I want to share some of my thoughts here.

Question 1

  • It is better to create new BehaviorSubject object when you consider code maintenance and readability.
  • Instantly notify anything that is subscribed to the BehaviorSubject when the data changes. This will give you more complexity if you try to deal with different type of data with one object.

Question 2

As @Vivek pointed out your this.subscription will be override the last subscription on every new subscribe.

for this you can use Subscription class,

Represents a disposable resource, such as the execution of an Observable. A Subscription has one important method, unsubscribe, that takes no argument and just disposes the resource held by the subscription.

you can use this in two ways,

  • you can directly push the subscription to Subscription Array

     subscriptions:Subscription[] = [];
    
     ngOnInit(): void {
    
       this.subscription.push(this.dataService.getMessageTracker().subscribe((param: any) => {
                //...  
       }));
    
       this.subscription.push(this.dataService.getFileTracker().subscribe((param: any) => {
            //...
        }));
     }
    
     ngOnDestroy(){
        // prevent memory leak when component destroyed
        this.subscriptions.forEach(s => s.unsubscribe());
      }
    
  • using add() of Subscription

    subscriptions = new Subscription();
    
    this.subscriptions.add(subscribeOne);
    this.subscriptions.add(subscribeTwo);
    
    ngOnDestroy() {
      this.subscriptions.unsubscribe();
    }
    

A Subscription can hold child subscriptions and safely unsubscribe them all. This method handles possible errors (e.g. if any child subscriptions are null).

Hope this helps.. :)



来源:https://stackoverflow.com/questions/57562345/using-a-single-subscription-variable-with-behaviorsubject

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!