Interview question
Stop a third-party Angular widget from leaking after navigation
Wraps widget creation, listeners, observers, timers, and destruction in one lifecycle boundary and verifies repeated navigation does not accumulate resources.
TL;DR
Wraps widget creation, listeners, observers, timers, and destruction in one lifecycle boundary and verifies repeated navigation does not accumulate resources.
Angular lifecycle, DestroyRef, third-party widgets, listeners, ResizeObserver, timers, retained DOM, and memory-leak regression testing.
Practice the problem like a real interview: restate, reason, implement, and test.
Wrap a chart SDK that creates an instance, installs a window resize listener, and starts a ResizeObserver. Repeated route navigation currently leaves old charts and callbacks alive. Implement one adapter that owns setup and idempotent teardown, then integrate it with an Angular component and test that every resource is released exactly once.
navigate to chart 10 times -> 10 creations, 10 destructions
active resize listeners after leaving -> 0
active observers after leaving -> 0
destroy called twice -> no duplicate SDK destruction
dispose idempotent and release every owned resource.class ChartAdapter {
private disposed = false;
private readonly chart: ChartInstance;
private readonly observer: ResizeObserver;
private readonly onResize = () => this.chart.resize();
constructor(host: HTMLElement, sdk: ChartSdk) {
this.chart = sdk.create(host);
this.observer = new ResizeObserver(() => this.chart.resize());
this.observer.observe(host);
window.addEventListener('resize', this.onResize);
}
dispose(): void {
if (this.disposed) return;
this.disposed = true;
window.removeEventListener('resize', this.onResize);
this.observer.disconnect();
this.chart.destroy();
}
}
@Component({selector: 'app-chart-host', template: '<div #host></div>'})
export class ChartHost implements AfterViewInit {
private readonly host = viewChild.required<ElementRef<HTMLElement>>('host');
private readonly sdk = inject(ChartSdk);
private readonly destroyRef = inject(DestroyRef);
ngAfterViewInit(): void {
const adapter = new ChartAdapter(this.host().nativeElement, this.sdk);
this.destroyRef.onDestroy(() => adapter.dispose());
}
}
Setup and teardown are O(1) per component instance; the SDK controls the chart's internal rendering complexity.
Next in Angular Practical Labs: Service-worker update prompt