From 3790dafb20b80e2d367289825998ce59c0ef443f Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Thu, 24 Sep 2020 14:05:41 +0800 Subject: [PATCH] Merge pull request #12514 from Marklb/marklb/unsub-prop-subscriptions Angular: Unsubscribe prop subscriptions --- .../angular/components/app.component.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/app/angular/src/client/preview/angular/components/app.component.ts b/app/angular/src/client/preview/angular/components/app.component.ts index f0a094788c9d..81d2cada177c 100644 --- a/app/angular/src/client/preview/angular/components/app.component.ts +++ b/app/angular/src/client/preview/angular/components/app.component.ts @@ -33,6 +33,8 @@ export class AppComponent implements OnInit, OnDestroy { subscription: Subscription; + propSubscriptions = new Map(); + constructor( private cfr: ComponentFactoryResolver, private changeDetectorRef: ChangeDetectorRef, @@ -64,6 +66,13 @@ export class AppComponent implements OnInit, OnDestroy { if (this.subscription) { this.subscription.unsubscribe(); } + + this.propSubscriptions.forEach(v => { + if (!v.sub.closed) { + v.sub.unsubscribe(); + } + }) + this.propSubscriptions.clear(); } /** @@ -93,7 +102,7 @@ export class AppComponent implements OnInit, OnDestroy { } } } else if (typeof value === 'function' && key !== 'ngModelChange') { - instanceProperty.subscribe(value); + this.setPropSubscription(key, instanceProperty, value); } }); @@ -123,4 +132,26 @@ export class AppComponent implements OnInit, OnDestroy { instance.registerOnChange(props.ngModelChange); } } + + /** + * Store ref to subscription for cleanup in 'ngOnDestroy' and check if + * observable needs to be resubscribed to, before creating a new subscription. + */ + private setPropSubscription(key: string, instanceProperty: Observable, value: any): void { + if (this.propSubscriptions.has(key)) { + const v = this.propSubscriptions.get(key); + if (v.prop === value) { + // Prop hasn't changed, so the existing subscription can stay. + return; + } + + // Now that the value has changed, unsubscribe from the previous value's subscription. + if (!v.sub.closed) { + v.sub.unsubscribe(); + } + } + + const sub = instanceProperty.subscribe(value); + this.propSubscriptions.set(key, { prop: value, sub }); + } }