angularrxjsangular2-observables

take(1) vs firstValueFrom vs observable.value


In my project, I use BehaviorSubjects as data stores to store the state of my application.

I need only the current value that is currently held in the BehaviorSubject store, and don't need to subscribe to future values that can be emitted through the behavior subject.

I found few implementations of how to do this: using pipe(take(1)), firstValueFrom and .value.

Do all work the same way and read the current value in the BehaviorSubject store? What are the differences between them, if any?

private myStore$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

// reading only one current value using take(1):
this.myStore$.pipe(take(1))
    .subscribe(value => console.log('current value = ', value));

// reading only one current value using firstValueFrom:
const value = await firstValueFrom(this.myStore$);
console.log('current value = ', value);

// reading only one current value using this.myStore$.value:
const value = this.myStore$.value;
console.log('current value = ', value);

Solution

  • Basically using take(1) or firstValueFrom is the same because they access the value asynchronously:

    myStore$.pipe(
      take(1)
    ).subscribe(value => {...});
    

    firstValueFrom turns Observable into a Promise so you can use async/await:

    const value = await firstValueFrom(myStore$);
    

    Using BehaviorSubject.value to synchronously access its value is in general not recommended. It might behave unexpectedly if BehaviorSubject errors or when it's unsubscribed:

    import { BehaviorSubject } from 'rxjs';
    
    const subject1 = new BehaviorSubject(1);
    console.log(subject1.value);
    subject1.error(new Error('broken'));
    try {
      console.log(subject1.value);
    } catch (e) {
      console.error(e);
    }
    
    const subject2 = new BehaviorSubject(2);
    console.log(subject2.value);
    subject2.unsubscribe();
    try {
      console.log(subject2.value);
    } catch (e) {
      console.error(e);
    }
    

    Live demo: https://stackblitz.com/edit/rxjs-npalak?devtoolsheight=60