Darwin Zaldarriaga
Darwin Zaldarriaga

Reputation: 15

How to prevent rxjs pipe operator from looping through two user/system defined inputs

I'm using Angular with Ngrx. I currently have a DataSource that loads data from the store, but if not found, a service call will be made to the back end to fetch required data.

My problem is that whenever I pass a new argument to the load method inside the DataSource, It loops through the previous and the new values (ex. 1, 2, 1, 2, 1, 2, .....)

So far with the rxjs take(1) operator, this stops the infinite loop but there are times where the previous data is the one being mapped and not the new ones.

I have tried searching online on how/why this happens but found none, or maybe I'm just using the wrong keywords.

This is the load method that I have mentioned above

 load(departmentId: number) {
    this.store.pipe(
      take(50),
      select(selectDepartmentSignatories(departmentId)),
      tap((signatories: SignatoryListItem[]) => {
        if (!!signatories && signatories.length > 0) {
          //map signatory details
        } else {
          this.store.dispatch(DepartmentSignatoriesRequested({ payload: { departmentId } }));
        }
      })
    ).subscribe();
  }

EDIT: Added the action dispatch in the else statement

Upvotes: 0

Views: 415

Answers (2)

Pankaj
Pankaj

Reputation: 568

The reason this is happening is because the observable is getting subscribed on each load. Instead use Subject for this.

loadDept$: Subject = new Subject<number>();

  ngOnInit() {
    const loadDeptSub$ = this.loadDept$.pipe(
      switchMap(deptId => {
        return this.store
          .pipe(
            select(selectDepartmentSignatories(departmentId)),
            map((signatories: SignatoryListItem[]) => {
              return {
                signatories, departmentId
              }
            }),
            take(1)
          );
      })

    );

    loadDeptSub$.subscribe(payload => {
      if (payload.signatories && payload.signatories.length) {
        //do something
      } else {
        this.store.dispatch(DepartmentSignatoriesRequested({ payload: { departmentId } }));
      }
    });
  }

  load(departmentId: number) {
    this.loadDept$.next(departmentId);
  }

Also, don't forget to unsubscribe, else you'll introduce a memory leak.

Upvotes: 0

Adrian Brand
Adrian Brand

Reputation: 21658

You should be dispatching a load action and the logic should be in an effect. Having your logic in a tap is not they way to do things.

Upvotes: 1

Related Questions