BehaviorSubject和Local Storage

时间:2016-07-08 07:05:19

标签: ionic-framework angular rxjs behaviorsubject

我仍然试图围绕rxjs和observables以及BehaviorSubject。我想要做的是,结合BehaviorSubject和LocalStorage,以便在特定的LocalStorage变量发生变化时通知所有组件。

例如,请考虑以下方案。

  • Component1和Component2有两个组件。

  • 这两个组件都在LocalStorage中查找名为Component1和Component2的变量,它包含一种颜色,并显示该颜色的正方形。

Component1需要在LocalStorage中订阅“Component1Color”键,而Component2需要在LocalStorage中订阅“Component2Color”。

执行此操作的一种方法是使用BehaviorSubject维护LocalStorage的状态,并且只要对任何变量进行更改,就会将此消息广播到已订阅BehaviorSubject的所有组件。

这种方法的问题在于,当Component2Color更新时,component1也会得到通知,并且不会对它做任何事情。

什么是好的,只有当Component1Color更新时,Component1才会得到通知,而只有在更新Component2Color时才会通知Component2。有没有办法可以使用一个BehaviorSubject来完成?

1 个答案:

答案 0 :(得分:2)

您可以通过StorageEvent

收听存储事件
const storage = Rx.Observable.fromEvent(window, 'storage').groupBy(ev => ev.key);

然后您可以通过执行以下操作来访问每个流:

let component1Stream = storage.filter(x => x.key === 'Component1Color').merge();

//Or using flatMap
let component2Stream = storage.flatMap(x =>
  x.key === 'Component2Color' ? x : Rx.Observable.empty()
);

修改

正如评论中指出的那样,存储事件仅对跨页面更新有用,如果您在同一页面上,它将不会更新。幸运的是,解决方案几乎完全相同,您只需要为localStorage对象提供一个装饰器对象,以便它可以发出事件。

class RxLocalStorage {
  private _subject: Rx.Subject<any>;
  private _updates: Observable<any>;
  constructor() {
    this._subject = new Rx.Subject();
    this._updates = this._subject.groupBy(ev => ev.key)
      .share();
  }
  getItem(key) { return this._updates.filter(x => x.key === key).merge(); }
  setItem(key, newValue) {
    const oldValue = localStorage.getItem(key);
    const event = {key, newValue, oldValue};
    localStorage.setItem(newValue);
    this._subject.next(event);
  }
}


let myLocalStorage = new RxLocalStorage();
myLocalStorage.getItem('Component1Color')
  .subscribe(x => console.log('Component1 Color changed'));

myLocalStorage.setItem('Component1Color', 'blue');
//-> Component1 Color changed

请注意,上述内容假设您在开始进行更改之前已完成所有订阅。