【问题标题】:Angular - a component loads before a service fetches necessary informationAngular - 在服务获取必要信息之前加载组件
【发布时间】:2017-07-20 13:30:44
【问题描述】:

我目前正在努力解决可观察的问题。我想我没有正确理解 rxjs 的主要概念。这就是我想要实现的目标。

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

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

product-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)
  }
}

(...)

【问题讨论】:

标签: javascript angular rxjs observable angular2-observables


【解决方案1】:

您在正确的轨道上,但我想补充两点。你可以用任何一个来解决你的问题,但我认为两者都是有效的。

服务应该通过 observables 暴露状态

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

product-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);
  });
}

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

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

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

现在让我们假设您确实需要准备好标志。例如,也许您有几个组件显示一些“数据加载”标志,直到所有初始应用程序数据(可能来自多个服务)都被加载。但是,出于举例目的,我们将仅解决您在某个主题上的初始问题。因此,让您的组件保持原样,我们可以将您的服务修改为...

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

【讨论】:

  • 感谢您的意见!看起来主题正是我想要的。我会记住其他解决方案的优点。
猜你喜欢
  • 2019-02-27
  • 2022-11-30
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2019-11-25
  • 2018-02-14
  • 2020-05-07
  • 2019-04-29
相关资源
最近更新 更多