在BehaviorSubject中使用单个订阅变量

时间:2019-08-19 18:45:16

标签: angular typescript rxjs behaviorsubject

我在BehaviorSubject应用中使用了Angular,从Details可以观察到DataService组件,如下所示:

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();
}

我的问题是:

1)据我所知,如上所述,我应该为每个事件创建一个新的BehaviorSubject变量,例如messageCreateTracker(用于跟踪添加的新消息),fileCreateTracker(用于跟踪添加的新文件,messageUpdateTracker(用于跟踪更新的消息)。这一切都是真的吗?

2)DetailComponent中,我只为subscription的每个订阅使用了一个Observables变量。那是一个不好的方法吗?我应该为ngOnInit()中的每个订阅创建一个新的订阅变量吗?

2 个答案:

答案 0 :(得分:2)

回答查询1:

取决于开发人员的编码风格,或者取决于他的想法,您还可以传递事件和数据的类型,在这种情况下,您将只需要一个BehaviorSubject ,就像这样:

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

但是如果它变大,也会产生复杂性,收益取决于项目的要求,您的方法也很好


回答查询2:

基本上,您无法处理多个订阅,因为它将覆盖上一个订阅,而只会取消订阅最后一个订阅:

因此,您可以为订阅的或单个数组/对象创建多个变量,然后取消所有订阅:

使用数组:

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();
    })
}

使用对象:

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();
    }
}

答案 1 :(得分:1)

虽然标记的答案已得到很好的解释,但我想在这里分享我的一些想法。

  

问题1

  • 考虑代码维护和可读性时,最好创建新的 BehaviorSubject 对象。
  • 当数据更改时,立即通知订阅了 BehaviorSubject 的任何内容。如果您尝试使用一个对象处理不同类型的数据,这将给您带来更多的复杂性。
  

问题2

@Vivek指出,您的this.subscription将在每个新订阅上覆盖上一个订阅。

为此,您可以使用 Subscription 类,

  

表示可抛弃的资源,例如Observable的执行。订阅具有一种重要的方法,即取消订阅,该方法不带任何参数,而是仅处理订阅所拥有的资源。

您可以通过两种方式使用它,

  • 您可以直接将订阅推送到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());
      }
    
  • 使用add()中的 Subscription

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

Subscription 可以保留子订阅,并可以安全地取消订阅所有子订阅。此方法处理可能的错误(例如,如果任何子订阅为空)。

希望这会有所帮助..:)