wonderful world
wonderful world

Reputation: 11599

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))
            )
          ))));

Upvotes: 1

Views: 1844

Answers (2)

wonderful world
wonderful world

Reputation: 11599

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)))
          )
        })));

Upvotes: 1

Tony
Tony

Reputation: 20132

You can use condition effect like this

@Effect()
    getMemberInfo$: Observable<Action> = this.actions$
    .ofType<memberAction.GetMember>(
        memberAction.MemberActionTypes.GetMember
    )
    .switchMap((action) => {
        let obs;
        this.store.select(getMember).take(1).subscribe(res => {
            const existsInStore = res.length > 0;
            if (existsInStore) {
              let member: IMember = res.find(x => x.id === action.payload);
              member = {
                  ...member
              };

              obs = new memberAction.GeMemberSuccess(member);
            } else {
              obs = this.memberService.getMember(action.payload)
                .map(member => {
                    return new memberAction.GeMemberSuccess(member);
                });
            }

        });
        return obs;
    });

Upvotes: 0

Related Questions