Необходимо ли заполнение темы при использовании шаблона takeUntil для отмены подписки на Observables? - PullRequest
0 голосов
/ 02 февраля 2019

Чтобы избежать утечек памяти в моем приложении Angular, я использую следующий хорошо известный шаблон для отмены подписки на Observables:

unsubscribe = new Subject();

ngOnInit() {
    this.myService.getStuff()
        .pipe(takeUntil(this.unsubscribe))
        .subscribe(result => {
            // processing the result
        });
}

ngOnDestroy() {
    this.unsubscribe.next();
}

Это, похоже, работает нормально, но в некоторых примерах я заметил, что complete() также вызывается на Subject в дополнение к next():

ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete(); // like this
}

Нужен ли здесь complete()?Если так, то почему?Каковы последствия отказа от вызова complete() в этом сценарии?

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Давайте посмотрим, почему вам нужно сначала отписаться.

Очень упрощенно: Наблюдаемый экземпляр содержит массив всех подписок, что означает, что все обратные вызовы, которые есть в вашем subscribe, будут храниться в этом массиве.Это плохая новость для Компонента, потому что, несмотря на то, что он передается из этих функций, он не может быть собран мусором.Я говорю об этих функциях:

ngOnInit() {
    this.myService.getStuff()
        .subscribe(
            result => null, // this function will be stored in Observable
            error => null, // and this
            () => null, // and even this
        );
}

, и это применимо к каждому subscribe вызову.

Теперь вы добавляете канал .pipe(takeUntil(this.unsubscribe)) (или вы можете, например, использовать myнебольшая библиотека , которая делает то же самое, но короче).Фактически, ваш Observable подписывается на события Subject.И всякий раз, когда он выдает значение, Observable, возвращаемый this.myService.getStuff(), завершается сам.Это означает, что все три вышеперечисленные функции будут удалены из массива подписок этого Observable, и ваш компонент больше не будет отсылаться оттуда.

Проблема решена.

Все вышесказанное вам необходимо понять все why с, которые у вас есть.

Здесь, наконец, мы подходим к вашему вопросу

ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
}

, где complete не нужно, но не наносит вреда.Потому что единственным подписчиком на эту тему был ваш Observable от this.myService.getStuff() (или другие Observables из того же компонента).Это означает, что этот субъект не будет ссылаться ни на что другое (единственный слушатель удален, а complete, который должен очистить все подписки, уже пуст), и до тех пор, пока только компонент имеет ссылку на субъект в качестве его свойства, они оба будутсобранные сборщиком мусора.

0 голосов
/ 02 февраля 2019

Это обсуждалось ранее, например.здесь Почему «следующий» до «полного» Angular takeun до ngUnsubscribe?

В принципе вам не нужно звонить complete(), потому что next() избавится от цепочки и takeUntilоткажусь от this.unsubscribe для вас.Только если у вас есть какая-то другая логика, связанная с this.unsubscribe, тогда вам может понадобиться позвонить complete().

В любом случае, вы ничего не сломаете, если вызовите complete().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...