Search code examples
angularngrxangular-httpngrx-effects

How to cancel the ngrx effect if the store has already the cached data?


In my Angular app, I want to stop calling the server using the ProductService which has http if the store has already the data.

This is what I currently have. I get a stream from the store and check whether the store has products. If the store has already products, return that data. Otherwise proceed the flow, get the categoryId, call the server using the ProductService and return the data.

Am I doing the effect correctly?

loadProducts$ = createEffect(
    () => ({ debounce = 300, scheduler = asyncScheduler } = {}) =>
      this.actions$.pipe(
        ofType(ProductActions.LoadProducts),
        debounceTime(debounce, scheduler),
        switchMap(() => this.ProductStore.pipe(select(ProductSelectors.selectAllProducts))),
        switchMap((Products) => {
          if (Products.length != 0) {
            return ProductActions.LoadProductsSuccess({ Products });
          }

          return of(ProductActions.LoadProductsCancelled({ Products }));
        }),
        switchMap(() => this.store.pipe(select(fromRoots.getCategory))),
        switchMap((category) =>
          this.ProductService.getProducts(category.categoryId).pipe(
            map(Products => (ProductActions.LoadProductsSuccess({ Products }))),
            catchError(err => of(ProductActions.LoadProductsFailed(err))
            )
          ))));

Solution

  • I updated the effect per Flignats suggestion, and is follows:

      loadProducts$ = createEffect(
        () => ({ debounce = 300, scheduler = asyncScheduler } = {}) =>
          this.actions$.pipe(
            ofType(ProductActions.LoadProducts),
            debounceTime(debounce, scheduler),
            withLatestFrom(
              this.store.select(ProductSelectors.selectAllProducts),
              this.rootState.select(fromRoots.getcategory),
            ),
            switchMap(([action, existingProducts, category]) => {
    
              if (existingProducts.length > 0) {
                return of(ProductActions.LoadProductsSuccess({ Products: existingProducts }));
              }
    
              return this.ProductService.getProducts(category.categoryId).pipe(
                map(newProducts => (ProductActions.LoadProductsSuccess({ Products: newProducts }))),
                catchError(err => of(ProductActions.LoadProductsFailed(err)))
              )
            })));