Angular 8/9 - (Динамическая подписка): как автоматически выполнить forkJoin при получении Observables из коллекции? - PullRequest
1 голос
/ 15 января 2020

Первый шаг:

Представьте, что где-то в проекте есть объект с именем RouteObservables, который я хочу использовать (импортировать) во многих компонентах:

export const RouteObservables = {
  state$: 'this.route.paramMap.pipe(map(() => window.history.state))',
  url$: 'this.route.url',
  params$: 'this.route.params',
  queryParams$: 'this.route.queryParams',
  fragment$: 'this.route.fragment',
  data$: ' this.route.data'
};

Второй шаг:

Я хочу перейти к следующей ситуации (с помощью объекта RouteObservables выше):

 const state$ = this.route.paramMap.pipe(map(() => window.history.state));
 const url$ = this.route.url;
 const params$ = this.route.params;
 const queryParams$ = this.route.queryParams;
 const fragment$ = this.route.fragment;
 const data$ = this.route.data;

Третий шаг

Я хочу использовать ту же коллекцию RouteObservables для автоматического запуска forkJoin:

forkJoin([...Object.keys(RouteObservables)]).subscribe(
  (routeData: any) => {
    this.routeData = routeData;
  }
);

Зачем мне нужен объект RouteObservables?

Мне нужна упорядоченная последовательность для доступа к правильным данным (например, routeData[0] будет моим объектом состояния, потенциально переданным с предыдущего маршрута). Этот объект помогает мне не пропустить некоторые подписки, чтобы отписаться в конце (ngOnDestroy) тоже.

Мой вопрос (ы):

  • Каков наиболее эффективный способ объявить Observables в последовательности (меня интересует) в объекте (или в коллекции), чтобы я мог выполнять некоторые операции динамически?

  • Если не существует проверенного (современного) способа, как я могу перейти от первого шага ко второму шагу?

  • Можно ли вообще сэкономить второй шаг и более элегантно перейти к третьему шагу?

Edit1:

Кстати: forkJoin не работает с наблюдаемыми маршрутами (ActivatedRoute) таким образом, потому что наблюдаемые маршрута не завершены. Следующий подход работает, но мои вопросы все еще существуют:

// excerpt!
// routeData is a public property 

ngOnInit() {
    this.getAllRouteData();
}

getAllRouteData() {
  const state$ = this.route.paramMap.pipe(map(() => window.history.state));

  const url$ = this.route.url;
  const params$ = this.route.params;
  const queryParams$ = this.route.queryParams;
  const fragment$ = this.route.fragment;
  const data$ = this.route.data;

  forkJoin(
    state$.pipe(first()),
    url$.pipe(first()),
    params$.pipe(first()),
    queryParams$.pipe(first()),
    fragment$.pipe(first()),
    data$.pipe(first())
  ).subscribe(
    (routeData: any) => {
      this.routeData = routeData;
      this.start();
    },
    (error: any) => {
      console.log('Error: ', error);
    }
  );
}

Edit2: Текущий обходной путь (routeObservables на самом деле повторно не используется в других компонентах)

 getAllRouteData() {
    const routeObservables = [
      this.route.paramMap.pipe(map(() => window.history.state)),
      this.route.url,
      this.route.params,
      this.route.queryParams,
      this.route.fragment,
      this.route.data
    ];

    forkJoin(routeObservables.map(r => r.pipe(first()))).subscribe(
      (routeData: any) => {
        this.routeData = routeData;
      }
    );
  }

Почему я спрашиваю?

Моя самая большая проблема - «единственная ответственность», я стараюсь избегать копирования + вставки кода (например, routeObservables выше в каждом компоненте, который нуждается в маршруте, связанном с данные).

1 Ответ

1 голос
/ 15 января 2020

Итак, основная проблема в том, что у вас есть строковые значения, и вам нужно использовать их как Javascript объекты, верно? В этом случае вы можете использовать доступ к этим свойствам в квадратных скобках:

const keys = Object.keys(this.RouteObservables);
const sources = this.keys.map(key => this[this.RouteObservables.key]);

forkJoin(...this.sources).subscribe(
  (routeData: any) => {
    this.routeData = routeData;
  }
);

ps класс должен иметь this.route, введенный в его конструктор.

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

...