В случае let subject$ = new Subject();
очистки ссылок на Subject
и Subscription
будет достаточно, после этого все будет собираться мусором.
Риск утечки памяти становится реальным когда вы подписываетесь на Subject
в объекте, и вы не отмените подписку на Subject
перед очисткой всех ссылок на объект. В этом случае весь объект останется активным и не будет собираться мусором.
Давайте рассмотрим этот пример:
class BigClass {
constructor(observable) {
this.bigArray = new Array(9999999).fill(0);
observable.subscribe(x => this.result = x);
}
//...
}
let subject = new rxjs.Subject();
let bigObject = new BigClass(subject);
let bigObject1 = new BigClass(subject);
let bigObject2 = new BigClass(subject);
let bigObject3 = new BigClass(subject);
bigObject = null;
bigObject1 = null;
bigObject2 = null;
bigObject3 = null;
В этом примере при очистке всех ссылок на bigObject
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *], subject
по-прежнему имеет ссылку на обратный вызов x => this.result = x
, которая имеет ссылку на bigObject
, что делает его необратимым в целом.
Либо путем отписки, либо очистки subject
, это нарушит цепочку ссылок, которая поддерживает bigObject
, и он будет иметь право на сборку мусора.
Чтобы самостоятельно наблюдать за поведением, вы можете скопировать содержимое этого файла https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js в вашей консоли, затем скопируйте и вставьте пример кода. Вы заметите увеличение памяти в диспетчере задач. Создавая дамп кучи на вкладке «Память» в инструментах разработчика, вы сможете найти 4 объекта, введя BigClass
в поле поиска.
После этого введите subject = null;
в консоли , а затем создайте новый дамп кучи. Вы заметите, что 4 объекта исчезли.
В заключение, пока Observable
уничтожен, это не реальный риск утечки памяти, поскольку все подписки также будут уничтожены. Рискованными Observables
являются те, которые являются постоянными (например: присоединены к глобальному событию DOM с fromEvent
) и с обратными вызовами, ссылающимися на объекты, которые должны быть уничтожены.