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

时间:2017-07-20 13:30:45

标签: javascript angular rxjs observable angular2-observables

我目前正在与观察者斗争。我想我不能正确理解rxjs的主要概念。这就是我想要实现的目标。

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

我尝试做的是在onReady中实施productsService方法,在ProductShowComponent中订阅它,并在从API获取信息后显示产品。我认为如果onReady方法返回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)
  }
}

(...)

1 个答案:

答案 0 :(得分:0)

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

服务应通过observables公开状态

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

<强>产品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。

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

将主题用于动态应用程序状态

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

<强> 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