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

时间:2019-08-05 10:24:59

标签: angular typescript eventemitter behaviorsubject

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

CreateComponent:

export class CreateComponent implements OnInit {

    constructor(private eventProxyService: EventProxyService) { }

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

DetailsComponent:

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,但是如果两个不同的事件将不一致的数据传递给订户,则可能会出现问题。什么是正确的方法?

1 个答案:

答案 0 :(得分:2)

最简单的方法是创建类型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); }
}

添加/获取事件

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

添加/获取事件

// 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/...)
}