将单个订阅变量与 BehaviorSubject 一起使用

Using a single subscription variable with BehaviorSubject

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

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
}


详细组件:

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,我只是为 Observables 的每个订阅使用了一个 subscription 变量。这是一个糟糕的方法吗?我应该为 ngOnInit() 中的每个订阅创建一个新的订阅变量吗?

查询 1 的答案:

取决于开发者的编码风格,或者他的想法,你也可以用它传递事件和数据的类型,那样的话,你只需要一个BehaviorSubject,像这样:

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

但是这个也会造成复杂度如果变大了,增益就看项目的要求了,你的方法也不错.


查询 2 的答案:

基本上,您不能处理多个订阅,因为它会覆盖前一个订阅,而只会退订最后一个订阅:

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

数组:

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

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

Question 1

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

Question 2

正如@Vivek 指出的那样,您的 this.subscription 将覆盖每个新订阅的最后一个订阅。

为此你可以使用 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.

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

  • 可以直接推送订阅到订阅数组

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

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

希望这对您有所帮助..:)