Angular 9: BehaviorSubject не работает для удаленных данных - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь передать данные от любого к любому компоненту с помощью behaviorSubject. Все работает нормально для данных stati c. Но при передаче удаленных данных (из 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 обновляет категорию, shopParams и продукт в любое время, когда вызывается onChangeCategory, поэтому все подписчики (например, productCompnent) должны получить обновленное значение. Я могу получить обновленное значение category и shopParams в productCompnent, но для продукта я всегда получаю предпоследнее значение вместо последнего. Я не знаю, что мне не хватает.

Также продукт зависит от shopParams который сам зависит от категории и pageComponent, просто измените категорию. Я не знаю, есть ли простой способ обновить мои shopParams и product в productComponent, используя только один behaviorSubject для категории?

1 Ответ

0 голосов
/ 19 июня 2020

Измените методы 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, и продукт получит последнее значение только после активации подписки. но ваш код не будет ждать завершения getitems перед вызовом product.next. вот как работают асинхронные операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...