我可以为多个事件使用单个 BehaviorSubject 吗?

Can I use a single BehaviorSubject for multiple events?

Angular 8 中,我使用以下方法在添加新记录后刷新 Details 页面:

EventProxyService

export class EventProxyService {
    private eventTracker = new BehaviorSubject<any>(undefined);

    /* Allows subscription to the behavior subject as an observable */
    getEvent(): BehaviorSubject<any> {
        return this.eventTracker;
    }

    /* Allows updating the current value of the behavior subject */
    setEvent(param: any): void {
        this.eventTracker.next(param);
    }
}

创建组件:

export class CreateComponent implements OnInit {

    constructor(private eventProxyService: EventProxyService) { }

    triggerAnEvent(param: any): void {
        this.eventProxyService.setEvent(param);
    }
}

详细组件:

export class DetailsComponent implements OnInit {

    subscription;

    constructor(private eventProxyService: EventProxyService) { }

    ngOnInit() {
        this.subscription = this.eventProxyService.getEvent().subscribe((param: any) => {
            this.theTargetMethod(param);
        );
    }

    theTargetMethod(param) {
        this.record = param; //update record via new one passed from service
    }

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

该方法按预期工作,但有时会出现类似的事件,例如需要刷新Details页面的更新。所以,我想知道我是否应该为每个不同的事件创建一个新的 BehaviorSubject 对象 (eventTracker)、getEventsetEvent 方法,例如Update 事件?据我所知,可以使用单个 BehaviorSubject ,但是如果两个不同的事件向订阅者传递不一致的数据可能会出现问题。什么是正确的方法?

最简单的方法是创建一个类型 CustomEvent(不会将其命名为 Event,因为该类型已被使用)。您可以给它一个字段 eventType 或使用从 CustomEvent 扩展的 类 来区分使用哪种事件。

1。 eventType 字段

events.ts

export interface CustomEvent{
   eventType: 'Update' | 'OtherEvent';
   data: any; // Type unsafe, maybe narrow it down
}

EventProxy

export class EventProxyService {
    private eventTracker = new BehaviorSubject<CustomEvent>(undefined);
    getEvent(): BehaviorSubject<CustomEvent> { return this.eventTracker; }
    setEvent(param: CustomEvent): void { this.eventTracker.next(param); }
}

add/get 事件

// Services omitted, too long
// add new event
this.eventProxyService.setEvent({
    eventType: 'Update',
    data: {/* Your data here */}
});

// listen to events
this.subscription = this.eventProxyService.getEvent()
    // .filter(param => param.evenType === 'Update') // if you want only specific events
    .subscribe((param: CustomEvent) => {
        if (param.eventType === 'Update') {
            this.theTargetMethod(param);
        } else if (param.eventType === 'OtherEvent') {
            // do something else
        }
    );

2。事件类

events.ts

export class CustomEvent {}
export class UpdateEvent extends CustomEvent {
   constructor(
      public newData: Data // Use a specific type and as many fields as you need
   ) {}

}
export class OtherEvent extends CustomEvent {
   constructor(
      public otherData: OtherData// Use a specific type and as many fields as you need
   ) {}
}

EventProxy

export class EventProxyService {
    private eventTracker = new BehaviorSubject<CustomEvent>(undefined);
    getEvent(): BehaviorSubject<CustomEvent> { return this.eventTracker; }
    setEvent(param: CustomEvent): void { this.eventTracker.next(param); }
}

add/get 事件

// Services omitted, too long
// add new event
this.eventProxyService.setEvent(new UpdateEvent({
   /* Your data here */
}));

// listen to events
this.subscription = this.eventProxyService.getEvent()
    // .filter(param => param instanceof UpdateEvent) // if you want only specific events
    .subscribe((param: CustomEvent) => {
        if (param instanceof UpdateEvent) {
            this.theTargetMethod(param);
        } else if (param instanceof OtherEvent) {
            // do something else
        }
    );

3。多个主题

EventProxy

export type EventType: 'update' | 'other';

export class EventProxyService {
    // Use BehaviourSubject<SPECIFIC_TYPE> if possible
    private updateEventTracker = new BehaviorSubject<any>(undefined);
    private otherEventTracker = new BehaviorSubject<any>(undefined);

    setEvent(type: EventType, param: any): void { 
        this.getEventTrackerForType(type).next(param);
    }
    getEvent(type?: EventType): BehaviorSubject<any> { 
        return this.getEventTrackerForType(type);
    }

    private getEventTrackerForType(type?:EventType): BehaviorSubject<any> {
        switch(type) {
            case 'update': return this.updateEventTracker;
            case 'other': return this.otherEventTracker;
            // if no type specified, return ALL events as one Observable (bonus)
            default: return merge(
                this.updateEventTracker, 
                this.otherEventTracker
            )
        }
    }

    // alternatively, create setEvent/getEvent methods for each subject specifically (setUpdateEvent/getUpdateEvent/...)
}