javascript - Angular 2 中用于双向数据绑定(bind)的共享 RxJS 主题

标签 javascript angular typescript rxjs

我有一个用于应用程序设置的单例服务

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.getstorage.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/

相关文章:

javascript - CSS:将悬停动画与其他类相关动画分开

JavaScript/MooTools - 将元素保存在对象属性中比每次使用 $ ('elem' 访问更好)?

javascript - 当标签为粘性时转到另一个标签后内容不需要隐藏

javascript - 如何在 Angular 2 项目中使用 javascript 库

javascript - 在 Angular 2 App 中过滤多维数组

javascript - 如何编写简单的测试来检查 Angular 2 中 MatDialog 的行为?

javascript - 我可以为同一个 es lint 规则执行多个级别吗?例如 : error and warning for different paths

angular - 将 Cdk Overlay 放置在 angular/elements web 组件内

angular - 如何在 Angular 7/Typescript 中使用变量类名?

typescript - 使用异步函数订阅可观察对象是否安全