$scope.$on('$destroy') in modern Angular
Cleanup on $destroy becomes DestroyRef.onDestroy for arbitrary callbacks and takeUntilDestroyed for RxJS subscriptions.
Before · AngularJS
app.controller('LiveCtrl', function ($scope, $rootScope, $interval, Socket) {
var timer = $interval(refresh, 5000);
var off = $rootScope.$on('cart:updated', refresh);
Socket.on('price', onPrice);
$scope.$on('$destroy', function () {
$interval.cancel(timer);
off();
Socket.off('price', onPrice);
});
});After · Angularexport class LiveComponent {
private store = inject(CartStore);
private socket = inject(SocketService);
price = signal<Price | null>(null);
constructor() {
interval(5000)
.pipe(takeUntilDestroyed())
.subscribe(() => this.store.refresh());
const onPrice = (p: Price) => this.price.set(p);
this.socket.on('price', onPrice);
inject(DestroyRef).onDestroy(() => this.socket.off('price', onPrice));
}
}What changes
- takeUntilDestroyed() without arguments only works in an injection context such as the constructor; anywhere else, pass it a DestroyRef.
- DestroyRef.onDestroy registers a cleanup callback right next to the code that needs it.
- Template event bindings, the async pipe, toSignal and effect clean up by themselves when the component is destroyed.
Migration tip. Search the old code for $rootScope.$on, $interval and socket listeners that have no matching cleanup. Those are leaks today, so fix them during the move instead of porting them.
Related
- require (parent controllers)
- isolate scope (scope: {})
- $attrs.$observe
- $onInit / $onChanges / $onDestroy / $postLink
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn