2
votes

I am attempting to get the values of a BehaviorSubject. The values are returned but how to i utilized them to use them in a return true/false statement.

BehaviorSubject {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}
closed:false
hasError:false
isStopped:false
observers:[Subscriber]
thrownError:null
value:(...)
_isScalar:false
_value:Array(3)
0:"[email protected]"
1:"Bob Smith"
2:{adminUser: false, basicUser: true} length:3
__proto__:Array(0)
__proto__:Subject

My Behavior Subject has the following being sent to it. Why am i getting null at the start.

user: BehaviorSubject<User> = new BehaviorSubject<User>(null); 

// The behavior-roles of the user.

 this.afAuth.authState
                .switchMap(auth => {
                if (auth) {
                    /// signed in
                    const authData = this.db.list<User>('users/' + auth.uid).valueChanges();
                    console.log(authData);
                    return this.db.list<User>('users/' + auth.uid).valueChanges();
                } else {
                    /// not signed in
                    return Observable.of(null);
                }
                })
                // .subscribe(console.log); // check the subscription
                .subscribe((userData) => {
                console.log(userData);
                this.user.next(userData);
                // this.user.next(user);
                // console.log(this.user.next(userData));
                });
            }

The results i am having issues with:

Check Value false authguard.service.ts:39 
Route was False authguard.service.ts:26 
Check Value true

I run console.log and the value shows up null first therefore has a false response. Then it runs again and becomes true. This all happens after running the page initially. I need for my check value to be true on load.

3
.value() should do itKevin192291

3 Answers

5
votes

You should just be able to call the name of the BehaviorSubject with the .getValue() so something like:

let x = new BehaviorSubject<any>;
...
x.getValue()
1
votes

I got the same problem. I always get my initial value (which is null) and never the emitted values. skip()-method dosen't help me but the skipWhile()-method was the trick.

behaviorSubject.pipe(
   skipWhile(value => !value), // skip null values
   take(1)) // in my case, I need the value only once
   .subscribe(value => doYourWork());

Edit

If it possible, then it´s the best solution to switch to a ReplaySubject of size 1. You need no .skip() or .skipeWhile() anymore.
Here is an example.

// replaySubjects have no initial value
let subject = new ReplaySubject<YourType>(1); 


subject.pipe(take(1)).
    // no null-values anymore!
    .subscribe(value => doYourStuff());

// subscribers dont get any value until a next()-call
subject.next(youValue);

// and you can hide some methods, when you declare it as observable or subject
// hide replaySubject specific informations
let publicSubject: Subject<YourType> = subject;
// hide subject informations (like .next())
let publicSubject2: Observable<YourType> = subject;
0
votes

I have officially answered my question. May not be the right way but it sure did work.

The BehaviorSubject from rxjs produces both the initial and current value at that particular steam of time. Now if you want to bypass the initial value (which in my case was null) then before you subscribe to it, make sure to use the skip operator.

Which I used in this case to skip the first value skip(1).

// RxJS v6+
import { interval } from 'rxjs';
import { skip } from 'rxjs/operators';

//emit every 1s
const source = interval(1000);
//skip the first 5 emitted values
const example = source.pipe(skip(5));
//output: 5...6...7...8........
const subscribe = example.subscribe(val => console.log(val));