How to cancel / close a behavior subject in angula

2020-07-23 05:53发布

问题:

I have a component that is subscribed to a behavior subject in the ngOnInit life cycle. This component html uses ngIf to see if data is there before rendering the table.

When I navigate away from the page, I am wanting to make sure that the next time I come back, the table isn't visible until that data is then fetched again. The only way I have been able to do this so far is by calling next on the subject and sending an empty string, which feels wrong..

Component:

mapMetaData: any;

ngOnInit() {

    // Subscribe to our map data
    this._mapsService.uiMapMetaData
    .subscribe(
        results => {
            if (results) {
                this.mapMetaData = results;
            }
        }
    );

}

/**
 * Implement onDestroy life cycle
 * 
 * @memberof ViewMapComponent
 */
ngOnDestroy() {
    this._mapsService.updateMapMetaData('');
}

HTML:

<span *ngIf="mapMetaData">
    <div class="page-header">
        <h3 class="text-primary">{{ mapMetaData.TargetName }} <small>{{ mapMetaData.TargetDesc }}</small>
            <button type="button" class="btn btn-default btn-sm pull-right" role="button" (click)="backToMaps()">
                <i class="fa fa-arrow-left"></i>&nbsp;&nbsp;Back to Maps
            </button>
        </h3>
    </div>
    <app-map-versions [targetID]="targetID"></app-map-versions>
    <app-map-exceptions [targetID]="targetID"></app-map-exceptions>
    <app-map-rules></app-map-rules>
</span>

The issue is, without sending the empty next to the behavior subject, mapMetaData still contains what it received from the previous next call, resulting in the table showing when I come back to it, containing old data, and then very quickly changing when new data is received.

Is there a better way to handle this or am I doing it correctly?

回答1:

You can use asObservable() to get a Observable from you BehaviorSubject and store the subscription object and ngOnDestroy you can unsubscribe :

In you mapServie class:

 private mapSubject = new BehaviorSubject<any>(mapdata()); /* you get the idea */
 public mapObservable = this.mapSubject .asObservable();

Then you can do the following:

mapMetaData: any;
subscription: Subscription;
ngOnInit() {

    this.subscription = this._mapsService.uiMapMetaData
    .subscribe(
        results => {
            if (results) {
                this.mapMetaData = results;
            }
        }
    );

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