使用自定义功能扩展Observable

pfo*_*oti 2 rxjs rxjs5

我的情况:我有一个数据存储,可以在其中获取可以使用RxJS Observables进行观察的模型。通用类型签名是

const foo = new Model({id: 123}, dataStore);
foo.asObservable().subscribe((v) => /* do stuff with values of this model */ );
Run Code Online (Sandbox Code Playgroud)

一般的观念是将数据视为可观察数据有两种方式:(a)当您遇到高速缓存情况(例如浏览器的localStorage包含一些过时的数据)但仍希望在实际数据显示时显示一些信息(b)当您已经加载了正确的数据时,但是在本地或在后端进行了更改,需要向上传播。到目前为止,这还算不错。

下一个问题是模型与其他模型有关系(例如,父母有很多孩子)。按照惯例,我可以做类似

foo.asObservable().subscribe(v => console.log(v.relationships.children))
Run Code Online (Sandbox Code Playgroud)

和(忽略此处的空错误),当将4添加到父子关系时,我会先得到[1、2、3],然后得到[1、2、3、4]。到目前为止和我在一起?

问题是我经常想以自己的权利访问这些子项,而不是以索引的形式,而是以可观察的模型访问(因此,我可以显示用户社区的所有成员的名字,例如,社区和所有成员是数据模型)。我目前在我的控制器代码中使用大量样板进行此操作,涉及到的许多调用.combineLatest

我想做的就是为这种类型的对象定义一个自定义运算符,这样我就可以将它们全部重做。理想的情况是:

foo.asObservable().inflateRelationship('members').subscribe(
  (v) => // v === [{name: 'steve'}, {name: 'gertude'} ...] etc
);
Run Code Online (Sandbox Code Playgroud)

我实际上有部分工作,但是问题是从实际链开始的。我正在遵循扩展Observable说明,创建一个新的实现的CustomObservable类lift,但是我的问题是我不能在这里使用静态的Observable方法(例如Observable.merge())在中生成我的初始Observable Model.asObservable

我的问题来了:

const preload$ = Observable... 
  // create the "load from cache and backend observable"
const update$ = Observable ... 
  // create the "update after load when the storage updates observable" 

return new CustomObservable(context).merge(preload$, update$);
Run Code Online (Sandbox Code Playgroud)

这是最后一行失败。我想在两个常规可观察流上返回由合并运算符制成的CustomObservable。我需要将上下文添加到那里的构造函数中,因为该上下文包含对实际膨胀子模型所需的数据存储的引用(没有这些,id数组的流是毫无意义的)。

这就是我的特定问题:我创建了一个Observable运算符,希望将其作为一个类添加到CustomObservable中,因此我只能像正常情况一样使用下游运算符,但似乎无法正确启动整个链。

欢迎使用任何指针,甚至指向正确(且不重要)扩展Observable类的现有项目。我试图深入研究源代码,但我什至无法弄清楚那部分内容(看起来Observable类静态变量已添加到其他位置,乍一看还不清楚,因为Observable类本身未定义任何内容) 。

pfo*_*oti 5

这是“写一个很长的问题以使堆栈溢出并在发布后不久找出答案”的一种情况,但是我认为我只是为了后代而写答案。

假设您已按照说明将Operator子类化,则您要做的是

asObservable() {
  // do a bunch of stuff making different things
  return Observable.merge(one$, two$)
    .let(obs => new CustomObservable(context, obs);
Run Code Online (Sandbox Code Playgroud)

然后在CustomObservable中

class CustomObservable extends Observable {
  constructor(context, source) {
    super();
    this.source = source;
  }
  customOperator() {}
  lift(operator) {
    const obs = new CustomObservable(context, this);
    obs.operator = operator;
    return obs;
  }
}
Run Code Online (Sandbox Code Playgroud)

这让我做

Model.asObservable()
.filter() // normal RxJs operator here
.customOperator() // yay
.map() // back to other RxJs operators
.subscribe(v => console.log(v)) // or whatever
Run Code Online (Sandbox Code Playgroud)

所以,是的。现在,我的角度模型可以看起来更多。

  • TSLint:`源已弃用:这是内部实现细节,请勿使用。(弃用)` (2认同)