我有一个用于应用程序设置的单例服务
class Setting {
get foo() {
return storage.get('foo');
}
set foo(val)
storage.set('foo', val);
}
}
在组件的 View 中绑定(bind)为 setting.foo
。
因为 storage
调用可能代价高昂并且可能是异步的,所以我更愿意用 RxJS 主题替换 getter/setter,以便在需要时更新和读取 storage
。
所以我将其重构为
class Setting {
constructor() {
this.fooSubject = new ReplaySubject(1);
fooSubject.subscribe((val) => {
storage.set('foo', val);
});
this.foo$ = this.fooSubject
.map(() => storage.get('foo'))
.publishReplay(1).refCount();
}
并像 setting.foo$ | 一样使用它异步
和setting.fooSubject.next(newFoo)
。看起来代价高昂的 storage.get
调用现在已被缓存。
有两个问题。
第一个是 fooSubject
subject 和 foo$
observable 都应该是公开可用的才能使这项工作有效,而选择 subject 是因为它应该是两者一个可观察对象和一个观察者。
能否将 foo$
设为 Setting
服务的单个 Subject 属性,以便使用 subscribe(...)
进行订阅> 并更新为 next(...)
?
第二个是代码仍然是同步的。
对于返回 promise 的 storage.get
和 storage.set
如何处理这种情况?
最佳答案
当您的代码真正按照您的意愿工作时,您的代码中没有太多建议。我不确定我是否完全理解您的用例,但我认为您可以通过完全不使用 this.foo$
来简化您的代码。
存储最新值的功能由ReplaySubject
提供除非你真的需要每次在 storage.set('foo', val);
之后调用 storage.get('foo')
,否则没有必要。
我将您的代码放入现场演示中:http://plnkr.co/edit/pxjRQr6Q6Q7LzYb1oode?p=preview
所以我觉得可以简化成这样。
class Setting {
constructor() {
var storage = new Storage();
this.fooSubject = new ReplaySubject(1);
this.fooSubject.subscribe((val) => {
storage.set('foo', val);
});
}
get observable() {
return this.fooSubject.asObservable();
};
store(val) {
this.fooSubject.next(val);
}
}
我故意隐藏了一个事实,即我正在使用一个带有 .asObservable()
的 Subject
并通过使用 store()
方法包装 .next()
调用。典型用法如下:
let settings = new Setting();
settings.store('Hello');
settings.observable.subscribe(val => console.log(val));
settings.store('Hello 2');
settings.store('Hello 3');
settings.observable.subscribe(val => console.log(val));
settings.store('Hello 4');
打印到控制台:
Hello
Hello 2
Hello 3
Hello 3
Hello 4
Hello 4
请注意,您没有使用任何值初始化 ReplaySubject
。即使您在创建 ReplaySubject
后立即调用了 setting.fooSubject.next(newFoo)
,它也会在使用 storage.set('foo) 订阅后立即再次存储', val);
.
关于同步的问题。好吧,您的代码实际上是异步但顺序的。由于 JavaScript 是单线程的,因此如果 storage.get('foo')
执行一些同步耗时操作,那么它将阻塞执行线程,可能唯一的选择是将其移至 Web Worker。
关于javascript - Angular 2 中用于双向数据绑定(bind)的共享 RxJS 主题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39781235/