Как объединить get .pipe takeUntil и подписаться в одну функцию в Angular с RxJX? - PullRequest
0 голосов
/ 08 октября 2019

В Angular каждый раз, когда требуется запросить конечную точку, этот код должен вызываться:

this.service.getSomeData()
 .pipe(takeUntil(this.onDestroy$))
 .subscribe((message: any) => { 
    some code here; 
 }

takeUntil - это функция в компоненте, которая отменяет подписку при уничтожении компонента.

Как изменить код, приведенный выше, чтобы не требовалось вводить все это каждый раз, когда используется ресурс? Так это выглядит в конце (более или менее?):

this.service.getSomeData(
   (message: any) => {
     some code here;
   }
)

Ответы [ 3 ]

3 голосов
/ 08 октября 2019

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


В: Почему все используют takeUntil(this.destroyed$) или this.subscription.unsubscribe()?

A: Observableживет до тех пор, пока есть хотя бы один подписчик. Поэтому, если у вас есть некоторые долгоживущие наблюдаемые, которые не завершаются сразу после какого-либо действия, у вас будут утечки памяти (Angular может создавать / инициализировать каждый компонент несколько раз). Говоря о Angular http, все вызовы get, post, put и delete завершаются после выполнения внутреннего вызова. Это означает, что вам не нужно добавлять unsubscribe в onDestroy hook или использовать takeUntil.

Если вы установили Websocket соединение и прослушиваете некоторые сообщения, ваш поток становится длинным-последний и каждый компонент, который подписан на этот сообщения должен отписаться в течение цикла onDestroy. Если вы этого не сделаете, Angular может инициализировать ваш компонент несколько раз (это обычно происходит с операторами *ngIf=""), и несколько подписок создаются, но никогда не уничтожаются. Это приводит к утечке памяти.

К сожалению, это общая проблема для большинства проектов Angular, которую можно решить либо вручную unsubscribe / takeUntil, либо с помощью канала async, который автоматически выполняет unsubscribe после уничтожения компонента.

3 голосов
/ 08 октября 2019

Один из вариантов - использовать асинхронный канал в вашем шаблоне для управления подписками

data$ = this.service.getSomeData();

и в вашем шаблоне

<ng-container *ngIf="data$ | async as data">
  {{ data | json }}
  You can use the template variable data here that magically updates every time data$
  emits and no need to unsubscribe as the async pipe manages the subscription for you
</ng-container>

Если наблюдаемое излучает данные, которых нет вформа, которая вам нужна для вашего шаблона, затем используйте функцию карты

data$ = this.service.getSomeData().pipe(map(data => functionThatTransformsData(data)));

Вы можете прочитать образец, который я использую с моей библиотекой управления состоянием здесь https://medium.com/@adrianbrand/angular-state-management-with-rxcache-468a865fc3fb

1 голос
/ 08 октября 2019

Я рад, что вы спросили, я наткнулся на эту Angular AutoUnsubscribe (я ссылаюсь на это, потому что я обнаружил, что логика для реализации этого действительно прекрасна.)

Это относительно легкоиспользовать и работает через все деклараторы (каналы, директивы и компоненты, очевидно.)

Теперь, чтобы пропустить как подписывающую, так и отписывающуюся часть (которую я не буду предлагать), она довольно простая и прямолинейная.

Раньше у вас было что-то вроде

getSomeData(): Observable<any> {
  // for eg
  return this.http.get();
}

Вы должны изменить его на:

getSomeData(callback, onDestroy$): Observable<any> {
  this.http.get(...).pipe(takeUntil(onDestroy$)).subscribe(val => callback(val));
}

Тогда мы сможем получить то, что, наконец, хотели. Приветствия.

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