Почему «следующий» перед «полным» Angular takeun до ngUnsubscribe? - PullRequest
0 голосов
/ 14 января 2019

Существует масса информации об использовании оператора takeUntil для отмены подписки на поток, например:

...

export class CategoryOptionInputComponent 

constructor(private svc: MyService, protected router: RouterService) {

  ...
  
  this.router.routerUrl$.pipe(takeUntil(this.ngUnsubscribe)).subscribe(s => {
      const param1 = s.state.featureId;
      this.svc.InitFromApi(param1);
    });
    
   ...
  }
  
    ngOnDestroy() {
    this.ngUnsubscribe.next();//<-- This line is confusing
    this.ngUnsubscribe.complete();
  }
  
  private readonly ngUnsubscribe = new Subject();
  
}

Как показано в приведенном выше коде, нам нужно было загрузить данные из API на анализируемые данные маршрутизатора и продолжать загружать новые данные при поступлении новых данных маршрутизатора, пока компонент не будет уничтожен.

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

Мои вопросы:

(1) Как предотвратить попадание компонента в API до его смерти?

(2) Почему бы просто не завершить () поток, почему вызов next () перед завершением () (см. Приведенный выше код)?

Спасибо, вперед.

1 Ответ

0 голосов
/ 14 января 2019

1) Если вы хотите, чтобы вызов API был отменяемым, он должен быть частью наблюдаемой цепочки. Когда вызов выполняется внутри subscribe, его нельзя отменить, поэтому для этого вам придется использовать оператор, например mergeMap или concatMap.

this.router.routerUrl$.pipe(
  takeUntil(this.ngUnsubscribe),
  concatMap(s => {
    const param1 = s.state.featureId;
    return this.svc.InitFromApi(param1);
  })
).subscribe();

Однако, это предполагает, что this.svc.InitFromApi() возвращает Observable или Promise. Если вы подписываетесь внутри InitFromApi() или используете then() в Обещании, тогда это становится невозможным.

2) Вот как устроен takeUntil. Он реагирует только на уведомления next. Если вы не хотите звонить как next(), так и complete(), вы можете использовать оператор defaultIfEmpty():

this.router.routerUrl$.pipe(
  takeUntil(this.ngUnsubscribe.pipe(
    defaultIfEmpty(null),
  ))
).subscribe(...);

Тогда вы можете позвонить только this.ngUnsubscribe.complete(), это также вызовет takeUntil.

На самом деле, в вашем примере вам даже не нужно звонить complete(), если вы звоните next(), потому что при следующем уведомлении цепочка будет выброшена.

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