简体   繁体   English

Angular Rxjs 如何使用行为主题进行分页

[英]Angular Rxjs How to paginate using Behavior Subject

I'm building a filtration for products list using categories ids and doing this by using the RXJS operator BehaviorSubject .我正在使用类别 ID 为产品列表构建过滤器,并使用 RXJS 操作符BehaviorSubject执行此操作。

My problem is I can't infinite scroll with Behavior Subject as I can't get the previous array of data ( products ) as obviously always get the latest data I update with.我的问题是我无法无限滚动 Behavior Subject,因为我无法获取先前的数据数组( products ),因为显然总是获取我更新的最新数据。

My Service:我的服务:

private productsSource = new BehaviorSubject<Product[]>(null);
public products$: Observable<Product[]> = this.productsSource.asObservable();
async getProductsByCategory(category: string, page: string = '1'): Promise<void> {
  const products = await this.http.get<Product[]>(`${environment.host + this.wooPath}products`, {
    params: {
      ...environment.configtations,
      category,
      page,
      lang: this.language,
      per_page: '6',
      not_tags: 'component'
    }
  })
    .toPromise();

  this.productsSource.next(products);
}

My loadMore ( Pagination ):我的加载更多(分页):

async loadData(event) {
 // what next?
}

Change this.productsSource.next(products);更改this.productsSource.next(products); to:到:

this.products.next({
   previous: this.products.value.current
   current: products
});

And the definition:和定义:

private productsSource = new BehaviorSubject<any>(null);
// You could also make a type for that like:
// { previous: Product[], current: Product[] }

And then you always have the previous one and the current one.然后你总是有前一个和当前的。

If you want to achive an infinite scroll, I would suggest you to change push all values into a dedicated array like:如果您想实现无限滚动,我建议您将所有值更改为专用数组,例如:

products$.subscribe((value) => {
   this.someProductsArray = [...this.someProductsArray, ...value];
});

I found a way to my situation that perfect fit,我找到了一种完美适合我的情况的方法,

The code for it:它的代码:

My service: Just returning a products list as a promise from the getProductsByCategory method:我的服务:只是从getProductsByCategory方法返回一个产品列表作为承诺:

/**
 * @name getProductsByCategory
 * @param category 
 * @param page 
 */
async getProductsByCategory(category: string, page: string = '1'): Promise<Product[]> {

  // getting products
  const products = await this.http.get<Product[]>(`${environment.host + this.wooPath}products`, {
    params: {
      ...environment.configtations,
      category,
      page,
      lang: this.language,
      // per_page: '6',
      not_tags: 'component'
    }
  })
    .toPromise();

  return products;
}

Then create a new method that returns the productsSource :然后创建一个返回productsSource的新方法:

filteringProduct() {
  return this.productSource;
}

On Component : in ngOnInit giving it an initial value:在组件上:在ngOnInit给它一个初始值:

async ngOnInit() {
  // get the category id
  const id = this.route.snapshot.paramMap.get('id');
  this.categoriesIds = id;

  // get gategory and its sub categories Or Prodicts by category id
  [this.category, this.subCatergories] = await Promise.all([
    this.wooService.getCategoryById(id),
    this.wooService.getSubCategories(id)]);

  // setting products
  this.wooService
    .filteringProduct()
    .next(
      await this.wooService.getProductsByCategory(this.categoriesIds)
    );

  this.wooService.products$
  .pipe(
    takeUntil(this.unsubscribe)
  )
  .subscribe(data => this.products = data);

}

My loadMore Methode:我的loadMore

async loadData(event) {

  // next page number
  this.currentPage++;

  // const id = this.category.id.toString();

  // next page content
  const nextPage = await this.wooService.getProductsByCategory(
    this.categoriesIds,
    this.currentPage.toString()
  );

  // concat all together
  this.products = this.products.concat(nextPage);

  // compelete the loading
  event.target.complete();

  // checking if all data loaded from the server
  if (nextPage.length === 0) {
    this.infinite = false;
  }

}

You can use count() operator to store the page number and just a normal subject will do the job.您可以使用count()运算符来存储页码,只需一个普通主题即可完成这项工作。

currentPage=Subject();
getProduct=(page)=>
this.http.get<Product[]>(`${environment.host + this.wooPath}products`, {
    params: {
      ...environment.configtations,
      category,
      page,
      lang: this.language,
      per_page: '6',
      not_tags: 'component'
    }
  })


data=loadMore.pipe(
  count(),
  mergeMap(page=>getProduct(page)),
     scan((acc,curr)=>{
         return acc.concat(cur.res)
     },[])
  )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM