0

In one Angular Component I'm dealing with three or four Observables. I need to refactor this some way in order to avoid this poorly written code with ugly nested subscribe calls. It's important as you can see that productService should be called before queryParamMap, while call to categoryService isn't crucial.

I tried to refactor this with forkJoin and switchMap but without success.

this.productService.getAll()
      .subscribe(
        (products: any) => {
          this.products = products;
          this.categoryService.getAll()
            .subscribe(categories => this.categories = categories);
          this.route.queryParamMap
            .subscribe(params => {
              this.category = params.get('category');

              if (this.category) {
                this.productService.getProductsByCategory(this.category)
                  .subscribe(fProducts => this.filteredProducts = fProducts);
              } else {
                this.filteredProducts = this.products;
              }
            },
              err => {
                console.log(err);
              }
            );
        });  

2 Answers 2

1

you can change your code like this

this.productService.getAll()
.pipe(
    switchMap(products => {
        this.products = products;
        return this.categoryService.getAll()
            .pipe(
                map(categories => this.categories = categories)
            );
    }),
    switchMap(() => this.route.queryParamMap
        .pipe(
            switchMap(params => {
                this.category = params.get('category');
                return defer(() =>
                    (Boolean(this.category) ?
                     this.productService.getProductsByCategory(this.category) :
                     of(this.products)
                    )
                );
            })
        )
    )
)
.subscribe((filteredProducts) => {
        this.filteredProducts = filteredProducts;
    },
    err => {
        console.log(err);
    }
);
Sign up to request clarification or add additional context in comments.

Comments

1

I think using forkJoin and switchMap is "right" approach and strange that it didn't work. Here is how I see it could be refactored.

forkJoin([
  this.productService.getAll(),
  this.categoryService.getAll()
])
.pipe(
  switchMap(([products, categories]) => {
    this.products = products;
    this.categories = categories;
    return this.route.queryParamMap;
  }),
  switchMap((params) => {
    this.category = params.get('category');
    return this.category ? this.productService.getProductsByCategory(this.category) : of(this.products);
  }),
  takeUntil(this.destroy$) // or take(1)
)
.subscribe((filteredProducts) => {
        this.filteredProducts = filteredProducts;
    },
    err => {
        console.log(err);
    }
);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.