Angular - Observables 组合结果多次调用

Angular - Observables combined result multiple calls

编辑 30-07-2018 01:57 CET: 仍在寻找以下问题的解决方案:

我有以下代码:

getBoolean(dataRef1, dataRef2) {
  const myFirstObservable = this.af.object(dataRef1).valueChanges();
  const mySecondObservable = this.af.object(dataRef2).valueChanges();

  return combineLatest(myFirstObservable, mySecondObservable).pipe(map(([data1, data2]) => data1 && data2)))
}

基本上代码所做的是:它结合了两个可观察对象的结果,然后检查每个对象是否具有 returned 任何值。如果两个 observables 都有一个值,return true else return false.

到目前为止一切顺利,一切都按预期进行。然后我从我的视图中调用该方法,为可观察对象提供动态节点引用,并使用布尔值添加条件元素:

<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>

但是,我的 div 根本没有显示在我的视图中。

谁能告诉我我哪里错了并帮助我达到我想要的结果?

getBoolean() return什么都没有。订阅回调中的 return 是订阅的 returning。一种实现此逻辑的方法。

getBoolean(dataRef1, dataRef2): Observable<boolean> {
  const myFirstObservable = this.af.object(dataRef1).valueChanges();
  const mySecondObservable = this.af.object(dataRef2).valueChanges();
  return combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2)
}

魔术:您使用 async 管道 link 在 HTML 中订阅,它将为您订阅:

<div *ngIf="getBoolean('dataN', 'dataK') | async"> My lovely div content goes here</div>

首先,您的应用程序陷入了无限循环,因为您使用 returned 函数绑定了您的视图,而该函数并没有 return 任何内容。此外,我不建议从视图绑定函数,而是绑定到变量。
您可能会尝试添加一个将视图和逻辑绑定到正确值的 BehaviorSubject。
我制作了一个沙箱来检查它是否有效,它确实有效。

TL;DR - I just construct two BehaviorSubject to manipulate the value of the third one, which in your case is the desired boolean value. I bind the div to the third BSubject through combineLatest and it works. The point is to keep always a valid variable to bind, which get updated via the subscription of the combineLatest, and I update its value through the BehaviorSubject


k1 = new BehaviorSubject<boolean>(false);
k2 = new BehaviorSubject<boolean>(false);
k3 = new BehaviorSubject<boolean>(false);
k3$: Observable<boolean>;

  constructor() {
    this.k3$ = this.k3.asObservable();
  }

  ngOnInit() {
    combineLatest(this.k1.asObservable(), this.k2.asObservable(), (d1, d2) => {
      return d1 && d2;
    }).subscribe(b => {
      console.log(b);
      this.k3.next(b);
    });
  }

  toggle1 = () => {
    this.k1.next(true);
  };
  toggle2 = () => {
    this.k2.next(true);
  };

并在 HTML 中:

<div *ngIf='k3$ | async'>
Example
</div>

有效,请尝试查看示例并将其投射到您的代码中。 Check the CodeSandbox Example


祝你好运!

问题很可能是您在模板中调用了 getBoolean('dataN', 'dataK') 方法。在每个变化检测中,Angular 调用 getBoolean 方法,return 是一个新的 Observable。旧的被async取消订阅,只有新的活跃。

同时 combineLatest 运算符要求所有源 Observable 至少发出一次,这不太可能发生,因为 async subscribes/unsubscribes 在可能发生的任何变化检测周期中一秒钟多次。

所以我建议您将 Observable 存储在 属性:

public obs$ = combineLatest(myFirstObservable, mySecondObservable, (data1, data2) => data1 && data2);

然后仅在模板中使用 obs$ | async

最后,您可以在 getBoolean 中添加一些逻辑来检查 obs$ 是否存在,如果存在,您将按原样 return 它。