3

The subscribe is running randomly when userId changes. Sometimes it does, sometimes i doesn't. userId variable is coming from a dropdown selector (Choices library).

Shouldn't subscribe always run even though userId is the only stream that changes?

Is there anything obvious that I'm am breaking or doing wrong?

this.singleUserControl.valueChanges
    .mergeMap((userId: number) => {
        this.router.navigate([ '/r', 'company-admin', 'user-claims', userId.toString() ]);
        this.userRoles = [];
        this.claims = [];
        const userRolesObserv: Observable<Array<RoleWithClaims>> =
            this.claimsService.getUserRoles(userId)
                .mergeMap((roles: Array<Role>) => {
                    const roleObservables = [];

                    for (const role of roles) {
                        roleObservables.push(this.claimsService.getClaimsForRole(role.id)
                            .mapTo(claims => ({
                                role: role,
                                claims: claims,
                            } as RoleWithClaims)));
                    }

                    return forkJoin(roleObservables);
                });

        return forkJoin([
            Observable.of(userId),
            userRolesObserv,
            this.claimsService.getAllClaimsForUser(userId),
        ]);
    })
    .subscribe((data: [ number, Array<RoleWithClaims>, Array<Claim>]) => {
        this.userSelectedId = data[0];
        this.userRoles = data[1]
        this.claims = data[2];
    }, (error) => {
        console.log(error);
    });
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Olafur Kari
  • 103
  • 4
  • forkJoin only emits when all of the items inside of it have completed. What you're likely seeing is that sometimes all items complete and sometimes they don't depending on all of the inner items – bryan60 Apr 12 '18 at 17:36
  • Looking at this code, you are already an expert in rxjs. One thing I would suggest is - did you check that the forkJoin will only emit values if all the observable completes, otherwise it won't emit values. If the userID observable is always active, forkJoin will never emit values. – Jay Apr 12 '18 at 17:44

1 Answers1

2

try doing this:

return (roleObservables.length) ? forkJoin(roleObservables) : Observable.of([]);

forkJoin won't emit with an empty array, so in this code, the subscribe wouldn't execute for any user id that didn't have roles associated.

In all my rx projects I have a utility function:

emptyJoin(obs: Observable<any>[]): Observable<any[]> => (obs.length) ? forkJoin(obs) : Observable.of([]);
bryan60
  • 28,215
  • 4
  • 48
  • 65