Я бы сказал, что утечек памяти не будет.
Это основано на моем понимании того, почему действительно происходят утечки памяти. Обычно такого рода проблемы возникают, когда источник бесконечен (например, не завершится / ошибка, как глобальная служба, которая используется компонентами).
Например, в Angular общий шаблон - внедрить сервис в области приложения в компоненты и подписаться на одно из наблюдаемых свойств, предоставляемых службой.
class Service {
private usersSrc = new Subject();
users$ = this.usersSrc.asObservable();
}
Затем вы должны сделать это в своем компоненте:
class FooComponent {
ngOnInit () {
this.subscription = this.service.users$.subscribe(() => {} /* callback */)
}
}
Примечание: это просто для демонстрационных целей, так как вы хотите использовать другие подходы, чтобы вам не приходилось подписываться вручную, например asyn c pipe
When users$
подписан, поскольку users$
происходит от usersSrc
, вновь созданный подписчик будет добавлен в список подписчиков Subject. И следующий обратный вызов этого подписчика будет () => {}
обратным вызовом.
Теперь, когда компонент уничтожен (например, из-за перехода по другому маршруту), если вы не сделаете что-то вроде this.subscription.unsubscribe()
, этот подписчик по-прежнему будет частью этого списка подписчиков. Метод unsubscribe
удалит этого подписчика из этого списка.
Таким образом, в следующий раз, когда будет создан компонент и будет создан этот ngOnInit
, будет добавлен новый подписчик , но старый остался бы там, если бы вы не использовали this.subscription.unsubscribe()
.
Я бы сказал, что установки этого источника на нуль будет достаточно.
Если источником окажется Subject
, вы также можете использовать Subject.unsubscribe
, хотя он может не иметь никакого значения.
unsubscribe() {
this.isStopped = true;
this.closed = true;
this.observers = null!;
}
Вот бы упрощенная версия. Вы можете вставить это в свою консоль.
src = {
subscribers: [],
addSubscriber(cb) {
this.subscribers.push(cb);
return this.subscribers.length - 1
},
removeSubscriber(idx) {
this.subscribers.splice(idx, 1)
},
next (data) {
this.subscribers.forEach(cb => cb(data));
}
}
// the component
class Foo {
constructor () {
this.subIdx = src.addSubscriber(() => { console.log('foo') })
}
onDestroy () {
src.removeSubscriber(this.subIdx);
}
}
// usage
// creating a new component
foo = new Foo() // Foo {subIdx: 0}
// sending data to subscribers
src.next('test')
// destroying the component - without calling `onDestroy`
foo = null
src.next('test') // the subscribers is still there
VM506:18 foo
foo = new Foo() // registering a new instance - Foo {subIdx: 1}
src.next('test2')
foo
foo
foo.onDestroy()
src.next('test2')
foo