Как я могу отказаться от всех подписок в моем приложении?

#angular #rxjs

#angular #rxjs

Вопрос:

У меня есть большое приложение, в котором у меня много методов подписки. Если я захочу отказаться от одной из них, то я буду использовать этот код:

 getUsersSubscription: Subscription;

ngOnInit() : void {

   this.getUsersSubscription = this.userService().subscribe(users => {
     ...something
   })
}

ngOnDestroy() : void {
   this.getUsersSubscription.unsubscribe();
}
  

Проблема в том, что у меня тоже много страниц — компонентов. У меня есть токен jwt, и когда срок его действия истекает, я выхожу из системы пользователя. Проблема в том, что когда я это делаю, некоторые вызовы все еще происходят… Как я могу отписаться от всех вещей в моем приложении после выхода из системы, чтобы мне не нужно было повторять этот шаг для всех моих подписок через все компоненты на моей странице?

Также я использую interceptr для отслеживания истечения срока действия jwt и перенаправляю пользователя на страницу входа в систему.Но есть вызовы, которые все еще выполняются на странице входа, если пользователь что-то нажимает — за несколько секунд до выхода из системы

Комментарии:

1. вы должны использовать intercepter и проверить код состояния. если вы получили 401, то перенаправьте на экран входа в систему.

2. Я использую это. Когда я перенаправляю на страницу входа, некоторые вызовы все еще выполняются, потому что не все подписки отписаны

Ответ №1:

Если вам нужно отказаться от подписки на многие из Observable , вам следует использовать Subscription массив:

 private subscriptions: Subscription[] = [];

ngOnInit() {
    this.subscriptions.push(this.userService.subscribe(users => {
     ...something
   }));
}

ngOnDestroy() {
    this.subscriptions.forEach(subscription => subscription.unsubscribe());
}
  

Но я думаю, что ваша реальная проблема в том, что у вас может быть больше подписки, чем вам нужно.

Во-первых, вы должны использовать async канал, когда это возможно. Он обрабатывает подписку и отписку очень хорошо и бесплатно.

Кроме того, имейте в виду, что вам обычно не нужно отписываться от холодных наблюдаемых (например, возвращаемых HttpClient ), потому что при выполнении http-запроса наблюдаемое завершается. Вам нужно отписаться только от холодных наблюдаемых, которые имеют побочные эффекты.

Комментарии:

1. Спасибо за ответ. Как я помещу свою this.getUsersSubscription в этот массив, когда он должен быть инициализирован подписью справа?

2. Извините, я забыл инициализировать массив. Я обновил пример

3. Массив инициализируется перед вводом кода ngOnInit . this.userService.subscribe(...) возвращает Subscription объект, который будет помещен в массив.

4. Кстати, вам действительно нужно отказаться от подписки на холодные наблюдаемые в приложении Angular, потому что, если есть ожидающий http-запрос, и вы меняете страницу на другой маршрут, запрос не будет отменен, если вы не откажетесь от подписки, которая доступна для onDestroy метода component.

5. @AliDemirci Спасибо за ваш комментарий. Если вы отмените подписку на холодный observable, http-запрос не будет отменен, но, по крайней мере, ваше приложение проигнорирует результат.

Ответ №2:

В отличие от предыдущих вариантов, вы также можете пойти по следующему маршруту:

Вы можете использовать takeUntil() оператор, который автоматически отменяет подписку для вас, как только происходит данное событие. Например:

В каком-то компоненте

 ...

myObservable$ = this.service.foo().pipe(
  takeUntil(this.loginService._loggedOutEmitter) <-- (0)
).subscribe()

...
  

В LoginService

 ...

_loggedOutEmitter = new Subject<boolean>(); <---- (1)

loggedOut() {
  *some logout logic *
  this._loggedOutEmitter.next(true); <----------- (2)
}

...
  

Так же, как и в других решениях, вам пришлось бы импортировать определенную службу и иметь определенную строку, которую вам нужно было бы добавить для каждого наблюдаемого (0), но этот способ должен быть немного более удобным с точки зрения памяти, поскольку вам не нужно было бы отслеживать свои подписки.
Вместо этого у вас есть только еще один наблюдаемый (1), который выдается один раз (2).

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