Angular - 在服务获取必要信息之前加载组件

Angular - a component loads before a service fetches necessary information

我目前正在为 observables 苦苦挣扎。我想我没有正确理解 rxjs 的主要概念。这就是我想要实现的目标。

在我的 Angular 应用程序中有一条通往 ProductShowComponent/product/:slug 路线。要显示所有必要的信息,我首先需要使用 ProductsService 从 API 中获取所有产品。关键是,可能会在组件加载后获取产品(例如,当用户在 /product/:slug 上刷新页面时)。

我想做的是在 productsService 中实现一个 onReady 方法,在 ProductShowComponent 中订阅它,并在从 [=] 中获取信息后显示产品40=]。我认为如果 onReady 方法 returns 和 Observable 监视 productsService.ready 值的变化是可能的,但我不知道该怎么做或者是否可能根本。也许有更好的方法来做到这一点?有什么想法吗?

产品-show.component.ts

(...)

public ngOnInit(): void {
  this.route.params.subscribe(params => {
    this.productsService.onReady().subscribe(() => {
      this.product = this.productsService.get(params['productSlug'], 'slug')
    })
  })
}

(...)

products.service.ts

(...)

constructor(
  private appClient: AppClient
) {
  this.fetchAll().subscribe((products: Product[]) => {
    this.products = products
    this.ready = true
  })
}

(...)

public onReady(): Observable<any> {
  if (!this.ready) {
    // return an observable that watches for changes of value of this.ready
  } else {
    return Observable.of(null)
  }
}

(...)

你的方向是正确的,但我想补充两点。你可以用其中任何一个来解决你的问题,但我认为两者都是有效的。

服务应通过可观察对象公开状态

在您的示例中,您的服务正在存储当前项目,然后公开该不可观察的状态。因此,例如,您可以...

产品-show.component.ts

public ngOnInit(): void {
  this.route.params.subscribe(params => {
    this.productsService.get(params['productSlug']).subscribe(product =>
      this.product = product;
    });
  });
}

products.service.component.ts

constructor(
  private appClient: AppClient
) {
  this.products = this.fetchAll().publish();
  this.productsSub = this.products.connect();
}

get(productId: string, idType: string) {
  return this.products.map(products => {
    return this.getProductFromProducts(products, productId, idType);
  });
}

现在您真的不需要为 ready 标志而烦恼,因为您可以在构建服务后立即调用 get。

另一个优点是,如果某些原因导致您的可用产品设置发生变化,那么您的组件将自动更新(前提是您的服务已扩展为在发生变化时重新获取数据)。

为动态应用程序状态使用主题

现在假设您确实需要就绪标志。例如,您可能有几个组件显示一些 "data loading" 标志,直到加载所有初始应用程序数据(可能来自多个服务)。但是,出于示例目的,我们将只解决您最初的主题问题。因此,保留您的组件,我们可以将您的服务修改为...

products.service.component.ts

constructor(
  private appClient: AppClient
) {
  this.ready = new BehaviorSubject<boolean>(false);
  this.fetchAll().subscribe((products: Product[]) => {
    this.products = products
    this.ready.next(true);
  });
}

由于主题是可观察的,因此您不需要 onReady 您可以直接订阅 ready