Angular: сбит с толку из-за связи между несвязанными компонентами без утечки памяти - PullRequest
0 голосов
/ 16 марта 2020

Из того, что я прочитал, предпочтительный способ взаимодействия несвязанных Angular компонентов - это создание службы и использование Rx JS BehaviorSubject. Вот одна из многих онлайн-ссылок на этот подход, которые я нашел:

https://fireship.io/lessons/sharing-data-between-angular-components-four-methods/

Для несвязанных компонентов этот сайт, как и другие, выступает за то, чтобы сделать что-то подобное в сервисе:

private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();

changeMessage(message: string) {
     this.messageSource.next(message)
}

Затем в другом компоненте:

ngOnInit() {
     this.data.currentMessage.subscribe(message => this.message = message)
}

Этот способ довольно прост, и я смог поделиться данными, используя этот подход. Однако в каждой ссылке, которую я читал о подписке, все они говорят, что важно отписаться, чтобы избежать утечки памяти. Кажется, нет никакого способа отписаться, используя этот подход. Есть ли что-то, что я неправильно понимаю, или какие-то дополнительные шаги требуются, чтобы избежать утечки памяти при использовании этого подхода? Есть ли какой-то подход, который я должен использовать вместо этого?

Ответы [ 3 ]

1 голос
/ 16 марта 2020

Вы можете легко отписаться в вашем компоненте ngOnDestroy метод:

OtherComponent implements OnInit, OnDestroy {

  private subscription: Subscription;

  //...

  ngOnInit() {
    this.subscription = this.data.currentMessage.subscribe(
      message => this.message = message
    );
  }

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

В качестве альтернативы вы можете сделать что-то причудливое с Rx Js takeWhile и предметом, который вы излучаете со значением на уничтожение.

Вы найдете это решение и другие замечательные примеры здесь, в этом блоге на Medium .

0 голосов
/ 16 марта 2020

Мои два цента на этом:

Мне нравится метод takeUntil, упомянутый в ссылке от Wilt (хотя он случайно упомянул takeWhile). Если вы довольны использованием наследования, у меня есть класс, который предназначен только для решения этой проблемы, а затем любой компонент, которому может потребоваться автоматическая отмена подписки на вещи, наследуется от него. Это будет выглядеть примерно так:

export class Unsubscriber implements OnDestroy {

    unsubscribe$: Subject<void> = new Subject()

    constructor() {}

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

Затем в вашем компоненте вы расширяете этот класс, обязательно добавляя следующее каждый раз, когда подписываетесь на что-то:

.pipe(takeUntil(this.unsubscribe$))

Итак, случай вашего класса:

export class MyClass extends Unsubscriber implements OnInit, OnDestroy {

  //...

    ngOnInit() {
        this.data.currentMessage.pipe(takeUntil(this.unsubscribe$)).subscribe(message => this.message = message);
    }
}

Мне нравится это, потому что он будет работать независимо от того, сколько подписок у вашего компонента в настоящее время. Единственное раздражение - это то, что вы постоянно добавляете эту трубу, хотя это не страшное бремя, и даже в существующем проекте это не слишком сложно исправить.

0 голосов
/ 16 марта 2020

Вы можете отказаться от подписки на ловушку жизненного цикла onDestroy вашего компонента.

subscription: Subscription

ngOnInit() {
 this.data.currentMessage.subscribe(message => this.message = message)
}

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

Это означает, что этот конкретный компонент будет отписываться от темы поведения, когда он будет уничтожен.

...