首页 > 解决方案 > Angular 8/9 -(动态订阅):如何在从集合中获取 Observables 时自动 forkJoin?

问题描述

第一步:

想象一下,在项目的某处有一个对象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;

第三步

我想使用相同的集合RouteObservablesforkJoin自动启动:

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

为什么我需要这个RouteObservables对象?

我需要有序序列来访问正确的数据(例如,routeData[0]将是我的状态对象可能从前一个路由转移)。这个对象也可以帮助我不要错过最后取消订阅的一些订阅(ngOnDestroy)。

我的问题:

编辑1:

顺便说一句: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,在每个组件中,需要路由相关数据)。

标签: angulartypescriptdynamicrxjs6fork-join

解决方案


所以主要问题是你有字符串值并且需要将它们用作 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在其构造函数中注入。

尚未测试,但我认为这应该可以解决问题。如果有任何错误,请告诉我。


推荐阅读