【问题标题】:Angular 9: BehaviorSubject not working for remote dataAngular 9:BehaviorSubject 不适用于远程数据
【发布时间】:2020-06-19 07:09:51
【问题描述】:

我正在尝试使用 behaviorSubject 在任何组件之间传递数据。静态数据一切正常。但是当传递远程数据(来自API)时,应该接收更新数据的组件正在接收更新之前的数据。我尝试了几件事,但我不知道我错过了什么。这是我的代码:

在我的服务中:appService

// BehaviorSubjects creation :
products = new BehaviorSubject<Array<IProduct>>([]);
currentProducts = this.products.asObservable();

category = new BehaviorSubject<string>('All Categories');
currentCategory = this.category.asObservable();

shopParams = new BehaviorSubject<ShopParams>(
    {brandId: [-1], CategoryId: 0, sort: 'name', pageNumber: 1, pageSize: 36, search: ''}
);
currentShopParams = this.shopParams.asObservable();

// Function to "update" the BehaviorSubject:
changeProducts(products: IProduct[]){
    this.products.next(products);
}
changeCategory(category: string){
    this.category.next(category);
}
changeShopParams(shopParams: ShopParams){
    this.shopParams.next(shopParams);
}
// Function to get data from API
getItems(shopParams: ShopParams) {
    let params = new HttpParams();
    shopParams.brandId.forEach(brandIdSlected =>{
        if (brandIdSlected !== -1) {
            params = params.append('brandId', brandIdSlected.toString());
        }
    });

    if (shopParams.CategoryId) {
        params = params.append('categoryId', shopParams.CategoryId.toString());
    }

    params = params.append('sort', shopParams.sort);
    params = params.append('pageIndex', shopParams.pageNumber.toString());
    params = params.append('pageSize', shopParams.pageSize.toString());

    return this.http.get<IPagination>(this.baseUrl + 'items', {observe: 'response', params})
    .pipe(
        map(response => {
          return response.body;
        })
      );
}

在我的第一个组件中:pageComponent

ngOnInit() {
    // Subscribe to category to get last update
    this.appService.currentCategory.subscribe(category => this.categoryNameSelected = category);
} 

// Method in which the category change
changeCategory(event){
    // some Code here  
    //Update category and shopParams for all suscribers
    this.appService.changeCategory(event);
    this.appService.changeShopParams(this.shopParams);  
    // Get the product from API base on category selected and new shopParams
    this.getItems();
   //Update products
    this.appService.changeProducts(this.products);
  }

// getItems function which call the getItem of my service to get data and subscribe
getItems() {
    this.appService.getItems(this.shopParams).subscribe(response => {
      this.products = response.data;
      this.shopParams.pageNumber = response.pageIndex;
      this.shopParams.pageSize = response.pageSize;
    }, error => {
      console.log(error);
    });   
  }

在我的第二个组件中:productCoponent

ngOnInit() {
    // Subscribe to category, shopParam and product to get last update
    this.appService.currentCategory.subscribe(category => this.categoryNameSelected = category);
    this.appService.currentShopParams.subscribe(shopParams => this.shopParams = shopParams);
    this.appService.currentProducts.subscribe(products => this.products = products);
}

pageComponent 假设在调用 onChangeCategory 时随时更新类别、shopParams 和产品,因此所有订阅者(如 productCompnent)都应该获得更新的值。 我可以在 productCompnent 中获取 category 和 shopParams 的更新值,但对于产品,我总是得到倒数第二个值而不是最后一个值,我不知道我错过了什么。

此外,产品依赖于 shopParams,它本身依赖于类别,而 pageComponent 只是更改类别。我不知道是否有一种简单的方法可以通过仅使用一个 behaviorSubject 来更新 productComponent 中的 shopParams 和产品?

【问题讨论】:

  • 如果您提供 stackblitz 将会很有用,这样任何人都可以更轻松地进行调试。当你引用 observables 时,还建议在变量名的末尾添加一个美元符号 $
  • 您的代码包含很多多余的 cmets,为了可读性考虑删除这些。
  • 另外,当您订阅行为主题时,请注意您在订阅时获得的第一个值:learnrxjs.io/learn-rxjs/subjects/behaviorsubject

标签: angular behaviorsubject


【解决方案1】:

将您的 changeCategory 和 getItems 方法更改为:-

changeCategory(event){
    // some Code here  
    //Update category and shopParams for all suscribers
    this.appService.changeCategory(event);
    this.appService.changeShopParams(this.shopParams);  
    // Get the product from API base on category selected and new shopParams
    this.getItems().subscribe(res => {
      this.appService.changeProducts(this.products);
    });
  }

// getItems function which call the getItem of my service to get data and subscribe
getItems() {
    return this.appService.getItems(this.shopParams).pipe(tap((response) => {
      this.products = response.data;
      this.shopParams.pageNumber = response.pageIndex;
      this.shopParams.pageSize = response.pageSize;
    }, error => {
      console.log(error);
    }));   
  }

说明 :- 您从 api 获取产品。您调用了 getitems,并且一旦调用订阅,产品只会收到最新值。但是您的代码不会在调用 product.next 之前等待 getitems 完成。这就是异步操作的工作原理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2017-08-07
    • 2018-09-22
    相关资源
    最近更新 更多