[Rxjs] Build a basic application store with Subjects

Store.js

import { BehaviorSubject, Subject } from 'rxjs';
import { map, distinctUntilKeyChanged, scan } from 'rxjs/operators';

export class ObservableStore {
  private _store: BehaviorSubject<any>;
  private _stateUpdate = new Subject();

  constructor(initialState) {
    this._store = new BehaviorSubject(initialState);
    this._stateUpdate.pipe(
      /*
       * Accumulate state over time using scan.
       * For this example we will just merge our current state
       * with updated state and emit the result, however
       * this could be any reducer / pattern you wish to follow.
       */
      scan((current, updated) => {
        return { ...current, ...updated }
      }, initialState)
    ).subscribe(this._store);
  }

  /*
   * Select a slice of state based on key.
   */
  selectState(key: string) {
    return this._store.pipe(
      distinctUntilKeyChanged(key),
      map(state => state[key])
    );
  }

  /*
   * Update state with new object to merge.
   */
  updateState(newState: object) {
    this._stateUpdate.next(newState);
  }

  /*
   * Subscribe to any store state changes.
   */
  stateChanges() {
    return this._store.asObservable();
  }
}

 

index.js

import { ObservableStore } from './store';

const store = new ObservableStore({
  user: 'joe',
  isAuthenticated: true
});

/*
 * Select a slice of state from store.
 */
store.selectState('user').subscribe(console.log);

/*
 * Update a property with new value.
 */
store.updateState({
  user: 'bob'
});

store.updateState({
  isAuthenticated: true
});

/*
 * Selected state above (user) only emits when value has changed
 * for the requested property.
 */
store.updateState({
  isAuthenticated: false
});

 

posted @ 2022-09-26 13:19  Zhentiw  阅读(19)  评论(0编辑  收藏  举报