Search code examples
angularrxjsbehaviorsubject

Best way to read and update a value of a BehaviorSubject


since it's well known that use getValue() method on a BehaviorSubject should be avoided link I'm wondering what's the best way to read and updated a BehaviorSubject.

In my case I've a BehaviorSubject storing an array of objects and when I click on a button I should push another object to the array and emit the new value to all the subscribers.

Right now I'm doing:

this.myBehaviorSubject.next([
    ...this.myBehaviorSubject.value,
    { new object }
])

Is there a better approach?

Thanks!!


Solution

  • Imperative is not good or bad, it depends on how you use it.

    Publish

    use next method. Here's what it looks under the hood :

    // update this._value and call Subject's next method 
    next(value: T): void {
        super.next(this._value = value);
    }
    
    // Subject's next method
    next(value?: T) {
        if (this.closed) {
          throw new ObjectUnsubscribedError();
        }
        if (!this.isStopped) {
          const { observers } = this;
          const len = observers.length;
          const copy = observers.slice();
          for (let i = 0; i < len; i++) {
            copy[i].next(value);
          }
        }
    }
    

    It's difficult to be more straightforward if you want to update the current value and send it to observers.

    Get the current Value

    The natural way to get values from any Observable is to subscribe to it. In most cases, getValue is really a bad idea because, in most cases, Observables are chained, used asynchronously. For example, if you want to merge or zip the values of two subscribers, the way to go is :

    zip(Subject_1, myBehaviorSubject).subscribe( val=> console.log(val));

    Now, in some cases, you just need to access the current value, synchronously, and without chaining operators. In this case, use getValue. Under the hood :

    getValue(): T {
        if (this.hasError) {
          throw this.thrownError;
        } else if (this.closed) {
          throw new ObjectUnsubscribedError();
        } else {
          return this._value;
        }
    }